Anpassa anspråk som utfärdats i JSON-webbtoken (JWT) för företagsprogram
Microsofts identitetsplattform stöder enkel inloggning (SSO) med de flesta förintegrerade program i Microsoft Entra-programgalleriet och anpassade program. När en användare autentiserar till ett program via Microsofts identitetsplattform med hjälp av OIDC-protokollet skickar den en token till programmet. Programmet validerar och använder token för att logga in användaren i stället för att fråga efter ett användarnamn och lösenord.
Dessa JSON-webbtoken (JWT) som används av OIDC- och OAuth-program innehåller information om användaren som kallas anspråk. Ett anspråk är information som en identitetsprovider anger om en användare i den token som de utfärdar för den användaren. I ett OIDC-svar finns anspråksdata vanligtvis i ID-token som utfärdats av identitetsprovidern i form av en JWT.
Visa eller redigera anspråk
Dricks
Stegen i den här artikeln kan variera något beroende på vilken portal du börjar från.
Valfria JWT-anspråk kan konfigureras i den ursprungliga programregistreringen, men de kan också konfigureras i företagsprogrammet. Så här visar eller redigerar du anspråken som utfärdats i JWT till programmet:
- Logga in på administrationscentret för Microsoft Entra som minst molnprogramadministratör.
- Bläddra till Identity>Applications Enterprise-program>>Alla program.
- Välj programmet, välj Enkel inloggning på den vänstra menyn och välj sedan Redigera i avsnittet Attribut och anspråk .
Ett program kan behöva anpassning av anspråk av olika skäl. Till exempel när ett program kräver en annan uppsättning anspråks-URI:er eller anspråksvärden. Med hjälp av avsnittet Attribut och anspråk kan du lägga till eller ta bort ett anspråk för ditt program. Du kan också skapa ett anpassat anspråk som är specifikt för ett program baserat på användningsfallet.
Följande steg beskriver hur du tilldelar ett konstant värde:
- Välj det anspråk som du vill ändra.
- Ange det konstanta värdet utan citattecken i källattributet enligt din organisation och välj sedan Spara.
Översikten Attribut visar konstantvärdet.
Omvandlingar av särskilda anspråk
Du kan använda följande funktioner för särskilda anspråkstransformeringar.
Function | beskrivning |
---|---|
ExtractMailPrefix() | Tar bort domänsuffixet från antingen e-postadressen eller användarens huvudnamn. Den här funktionen extraherar endast den första delen av användarnamnet. I stället joe_smith@contoso.com för joe_smith . |
ToLower() | Konverterar tecknen i det markerade attributet till gemener. |
ToUpper() | Konverterar tecknen i det markerade attributet till versaler. |
Lägga till programspecifika anspråk
Så här lägger du till programspecifika anspråk:
- I Användarattribut och anspråk väljer du Lägg till nytt anspråk för att öppna sidan Hantera användaranspråk .
- Ange namnet på anspråken. Värdet behöver inte följa ett URI-mönster. Om du behöver ett URI-mönster kan du placera det i fältet Namnområde .
- Välj den källa där anspråket ska hämta dess värde. Du kan välja ett användarattribut i listrutan för källattributet eller tillämpa en transformering på användarattributet innan du skickar det som ett anspråk.
Anspråkstransformeringar
Så här tillämpar du en transformering på ett användarattribut:
- I Hantera anspråk väljer du Transformering som anspråkskälla för att öppna sidan Hantera transformering .
- Välj funktionen i listrutan transformering. Beroende på vilken funktion som valts anger du parametrar och ett konstant värde som ska utvärderas i omvandlingen.
- Behandla källan som flervärdesvärde anger om transformeringen tillämpas på alla värden eller bara den första. Som standard används transformeringarna som det första elementet i ett anspråk med flera värden. När du markerar den här kryssrutan ser den till att den tillämpas på alla. Den här kryssrutan är endast aktiverad för flervärdesattribut. Exempel:
user.proxyaddresses
- Om du vill tillämpa flera transformeringar väljer du Lägg till transformering. Du kan använda högst två transformeringar för ett anspråk. Du kan till exempel först extrahera e-postprefixet för
user.mail
. Gör sedan strängens versaler.
Du kan använda följande funktioner för att transformera anspråk.
Function | beskrivning |
---|---|
ExtractMailPrefix() | Tar bort domänsuffixet från antingen e-postadressen eller användarens huvudnamn. Den här funktionen extraherar endast den första delen av användarnamnet. I stället joe_smith@contoso.com för joe_smith . |
Join() | Skapar ett nytt värde genom att koppla två attribut. Du kan också använda en avgränsare mellan de två attributen. För NameID-anspråkstransformering har funktionen Join() ett specifikt beteende när transformeringsindata har en domändel. Den tar bort domändelen från indata innan den kopplas till avgränsaren och den valda parametern. Om till exempel transformeringens indata är joe_smith@contoso.com och avgränsaren är @ och parametern är fabrikam.com resulterar den här indatakombinationen i joe_smith@fabrikam.com . |
ToLowercase() | Konverterar tecknen i det markerade attributet till gemener. |
ToUppercase() | Konverterar tecknen i det markerade attributet till versaler. |
Contains() | Matar ut ett attribut eller en konstant om indata matchar det angivna värdet. Annars kan du ange ytterligare utdata om det inte finns någon matchning. Om du till exempel vill generera ett anspråk där värdet är användarens e-postadress om det innehåller domänen @contoso.com , vill du annars ange användarens huvudnamn. För att utföra den här funktionen konfigurerar du följande värden:Parameter 1(indata): user.email Värde: "@contoso.com" Parameter 2 (utdata): user.email Parameter 3 (utdata om det inte finns någon matchning): user.userprincipalname |
EndWith() | Matar ut ett attribut eller en konstant om indata slutar med det angivna värdet. Annars kan du ange ytterligare utdata om det inte finns någon matchning. Om du till exempel vill generera ett anspråk där värdet är användarens medarbetar-ID om medarbetar-ID:t slutar med 000 , vill du annars mata ut ett tilläggsattribut. För att utföra den här funktionen konfigurerar du följande värden:Parameter 1(input): user.employeeid Värde: "000" Parameter 2 (utdata): user.employeeid Parameter 3 (utdata om det inte finns någon matchning): user.extensionattribute1 |
StartWith() | Matar ut ett attribut eller en konstant om indata börjar med det angivna värdet. Annars kan du ange ytterligare utdata om det inte finns någon matchning. Om du till exempel vill generera ett anspråk där värdet är användarens medarbetar-ID om landet/regionen börjar med US , vill du annars mata ut ett tilläggsattribut. För att utföra den här funktionen konfigurerar du följande värden:Parameter 1(input): user.country Värde: "US" Parameter 2 (utdata): user.employeeid Parameter 3 (utdata om det inte finns någon matchning): user.extensionattribute1 |
Extract() – Efter matchning | Returnerar delsträngen efter att den matchar det angivna värdet. Om till exempel indatavärdet är Finance_BSimon , är Finance_ matchande värde , är BSimon anspråkets utdata . |
Extract() – Före matchning | Returnerar delsträngen tills den matchar det angivna värdet. Om till exempel indatavärdet är BSimon_US , är _US matchande värde , är BSimon anspråkets utdata . |
Extract() – mellan matchning | Returnerar delsträngen tills den matchar det angivna värdet. Om till exempel indatavärdet är Finance_BSimon_US , är Finance_ det första matchande värdet , det andra matchande värdet är _US , så är BSimon anspråkets utdata . |
ExtractAlpha() – prefix | Returnerar prefixets alfabetiska del av strängen. Om till exempel indatavärdet är BSimon_123 returnerar BSimon det . |
ExtractAlpha() – Suffix | Returnerar suffixets alfabetiska del av strängen. Om till exempel indatavärdet är 123_Simon returnerar Simon det . |
ExtractNumeric() – prefix | Returnerar prefixets numeriska del av strängen. Om till exempel indatavärdet är 123_BSimon returnerar 123 det . |
ExtractNumeric() – Suffix | Returnerar suffixets numeriska del av strängen. Om till exempel indatavärdet är BSimon_123 returnerar 123 det . |
IfEmpty() | Matar ut ett attribut eller en konstant om indata är null eller tomma. Om du till exempel vill mata ut ett attribut som lagras i ett tilläggsattribut om medarbetar-ID:t för en viss användare är tomt. Konfigurera följande värden för att utföra den här funktionen: Parameter 1(input): user.employeeid Parameter 2 (utdata): user.extensionattribute1 Parameter 3 (utdata om det inte finns någon matchning): user.employeeid |
IfNotEmpty() | Matar ut ett attribut eller en konstant om indata inte är null eller tomma. Om du till exempel vill mata ut ett attribut som lagras i ett tilläggsattribut om medarbetar-ID:t för en viss användare inte är tomt. För att utföra den här funktionen konfigurerar du följande värden: Parameter 1(input): user.employeeid Parameter 2 (utdata): user.extensionattribute1 |
Delsträng() – Fast längd | Extraherar delar av en stränganspråkstyp med början vid tecknet vid den angivna positionen och returnerar det angivna antalet tecken. SourceClaim – anspråkskällan för den transformering som ska köras. StartIndex – den nollbaserade startteckenpositionen för en delsträng i den här instansen. Längd – längden i tecken i delsträngen. Till exempel: sourceClaim – PleaseExtractThisNow StartIndex - 6 Längd - 11 Utdata: ExtractThis |
Substring() – EndOfString | Extraherar delar av en stränganspråkstyp med början vid tecknet vid den angivna positionen och returnerar resten av anspråket från det angivna startindexet. SourceClaim – anspråkskällan för transformering. StartIndex – den nollbaserade startteckenpositionen för en delsträng i den här instansen. Till exempel: sourceClaim – PleaseExtractThisNow StartIndex - 6 Utdata: ExtractThisNow |
RegexReplace() | RegexReplace()-transformering accepterar som indataparametrar: – Parameter 1: ett användarattribut som regex-indata – Ett alternativ för att lita på källan som flervärdes – Regex-mönster - Ersättningsmönster. Ersättningsmönstret kan innehålla statiskt textformat tillsammans med en referens som pekar på regex-utdatagrupper och fler indataparametrar. |
Om du behöver andra transformeringar skickar du din idé i feedbackforumet i Microsoft Entra-ID under kategorin SaaS-program .
Regex-baserad anspråkstransformering
Följande bild visar ett exempel på den första omvandlingsnivån:
Följande tabell innehåller information om den första nivån av transformeringar. De åtgärder som anges i tabellen motsvarar etiketterna i föregående bild. Välj Redigera för att öppna bladet för anspråkstransformering.
Åtgärd | Fält | beskrivning |
---|---|---|
1 | Transformation |
Välj alternativet RegexReplace() från transformeringsalternativen för att använda den regex-baserade anspråkstransformeringsmetoden för anspråkstransformering. |
2 | Parameter 1 |
Indata för transformering av reguljära uttryck. Till exempel user.mail som har en e-postadress för användaren, admin@fabrikam.com till exempel . |
3 | Treat source as multivalued |
Vissa indataanvändarattribut kan vara användarattribut med flera värden. Om det valda användarattributet stöder flera värden och användaren vill använda flera värden för omvandlingen måste de välja Behandla källa som flervärdesvärde. Om du väljer det här alternativet används alla värden för regex-matchningen, annars används endast det första värdet. |
4 | Regex pattern |
Ett reguljärt uttryck som utvärderas mot värdet för användarattributet som valts som Parameter 1. Ett reguljärt uttryck för att extrahera användaraliaset från användarens e-postadress representeras till exempel som (?'domain'^.*?)(?i)(\@fabrikam\.com)$ . |
5 | Add additional parameter |
Mer än ett användarattribut kan användas för omvandlingen. Värdena för attributen sammanfogas sedan med regex-transformeringsutdata. Upp till fem parametrar stöds. |
6 | Replacement pattern |
Ersättningsmönstret är textmallen som innehåller platshållare för regex-utfall. Alla gruppnamn måste omslutas i klammerparenteserna, till exempel {gruppnamn}. Anta att administrationen vill använda användaralias med något annat domännamn, till exempel xyz.com och koppla landsnamn med det. I det här fallet skulle ersättningsmönstret vara {country}.{domain}@xyz.com , där {country} är värdet för indataparametern och {domain} är grupputdata från utvärderingen av reguljära uttryck. I sådana fall är US.swmal@xyz.com det förväntade resultatet . |
Följande bild visar ett exempel på den andra omvandlingsnivån:
Följande tabell innehåller information om den andra nivån av transformeringar. De åtgärder som anges i tabellen motsvarar etiketterna i föregående bild.
Åtgärd | Fält | beskrivning |
---|---|---|
1 | Transformation |
Regex-baserade anspråkstransformeringar är inte begränsade till den första omvandlingen och kan även användas som transformering på andra nivån. Alla andra transformeringsmetoder kan användas som den första omvandlingen. |
2 | Parameter 1 |
Om RegexReplace() väljs som en transformering på andra nivån används utdata från transformering på första nivån som indata för omvandlingen på andra nivån. Om du vill tillämpa transformeringen ska regex-uttrycket på andra nivån matcha utdata från den första omvandlingen. |
3 | Regex pattern |
Regex-mönstret är det reguljära uttrycket för transformering på andra nivån. |
4 | Parameter input |
Användarattributindata för omvandlingar på andra nivån. |
5 | Parameter input |
Administratörer kan ta bort den valda indataparametern om de inte längre behöver den. |
6 | Replacement pattern |
Ersättningsmönstret är textmallen, som innehåller platshållare för regex-resultatgruppnamn, indataparametergruppnamn och statiskt textvärde. Alla gruppnamn måste omslutas i klammerparenteserna, till exempel {group-name} . Anta att administrationen vill använda användaralias med något annat domännamn, till exempel xyz.com och koppla landsnamn med det. I det här fallet skulle ersättningsmönstret vara {country}.{domain}@xyz.com , där {country} är värdet för indataparametern och {domain} är grupputdata från utvärderingen av reguljära uttryck. I sådana fall är US.swmal@xyz.com det förväntade resultatet . |
7 | Test transformation |
Transformering av RegexReplace() utvärderas endast om värdet för det valda användarattributet för Parameter 1 matchar det reguljära uttrycket som anges i textrutan Regex-mönster . Om de inte matchar läggs standardanspråkvärdet till i token. För att validera reguljära uttryck mot indataparametervärdet är en testupplevelse tillgänglig på transformeringsbladet. Den här testupplevelsen fungerar endast på dummy-värden. När fler indataparametrar används läggs namnet på parametern till i testresultatet i stället för det faktiska värdet. Om du vill komma åt testavsnittet väljer du Testtransformering. |
Följande bild visar ett exempel på hur du testar transformeringarna:
Följande tabell innehåller information om hur du testar transformeringarna. De åtgärder som anges i tabellen motsvarar etiketterna i föregående bild.
Åtgärd | Fält | beskrivning |
---|---|---|
1 | Test transformation |
Välj knappen stäng eller (X) för att dölja testavsnittet och åter återge knappen Testtransformering igen på bladet. |
2 | Test regex input |
Accepterar indata som används för utvärdering av reguljära uttryckstest. Om regex-baserad anspråkstransformering konfigureras som en transformering på andra nivån anger du ett värde som är förväntade utdata från den första omvandlingen. |
3 | Run test |
När regex-testindata har angetts och Regex-mönstret, ersättningsmönstret och indataparametrarna har konfigurerats kan uttrycket utvärderas genom att välja Kör test. |
4 | Test transformation result |
Om utvärderingen lyckas renderas utdata från testtransformeringen mot resultatetiketten Testtransformering. |
5 | Remove transformation |
Den andra nivåtransformeringen kan tas bort genom att välja Ta bort transformering. |
6 | Specify output if no match |
När ett regex-indatavärde konfigureras mot parametern 1 som inte matchar reguljära uttryck hoppas transformeringen över. I sådana fall kan det alternativa användarattributet konfigureras, vilket läggs till i token för anspråket genom att kontrollera Ange utdata om det inte finns någon matchning. |
7 | Parameter 3 |
Om ett alternativt användarattribut måste returneras när det inte finns någon matchning och Ange utdata om ingen matchning är markerad kan ett alternativt användarattribut väljas med listrutan. Den här listrutan är tillgänglig mot Parameter 3 (utdata om ingen matchning). |
8 | Summary |
Längst ned på bladet visas en fullständig sammanfattning av formatet som förklarar innebörden av omvandlingen i enkel text. |
9 | Add |
När konfigurationsinställningarna för omvandlingen har verifierats kan den sparas i en anspråksprincip genom att välja Lägg till. Spara ändringarna genom att välja Spara på bladet Hantera anspråk. |
RegexReplace()-transformering är också tillgänglig för omvandlingar av gruppanspråk.
Transformeringsvalidering
Ett meddelande innehåller mer information när följande villkor inträffar när du har valt Lägg till eller Kör test:
- Indataparametrar med duplicerade användarattribut användes.
- Oanvända indataparametrar hittades. Definierade indataparametrar ska ha respektive användning i text för ersättningsmönster.
- Angivna regex-indata för test matchar inte det angivna reguljära uttrycket.
- Inga källor för grupperna i ersättningsmönstret hittas.
Generera anspråk baserat på villkor
Du kan ange källan för ett anspråk baserat på användartyp och den grupp som användaren tillhör.
Användartypen kan vara:
- Alla – Alla användare får åtkomst till programmet.
- Medlemmar: Intern medlem i klientorganisationen
- Alla gäster: Användaren har flyttat från en extern organisation med eller utan Microsoft Entra-ID.
- Microsoft Entra-gäster: Gästanvändare tillhör en annan organisation med hjälp av Microsoft Entra-ID.
- Externa gäster: Gästanvändaren tillhör en extern organisation som inte har Microsoft Entra-ID.
Ett scenario där användartypen är användbar är när källan till ett anspråk skiljer sig för en gäst och en anställd som har åtkomst till ett program. Du kan ange att om användaren är anställd hämtar du NameID från user.email. Om användaren är gäst kommer NameID från user.extensionattribute1.
Så här lägger du till ett anspråksvillkor:
- I Hantera anspråk expanderar du anspråksvillkoren.
- Välj användartyp.
- Välj de grupper som användaren ska tillhöra. Du kan välja upp till 50 unika grupper för alla anspråk för ett visst program.
- Välj den källa där anspråket ska hämta dess värde. Du kan välja ett användarattribut i listrutan för källattributet eller tillämpa en transformering på användarattributet innan du skickar det som ett anspråk.
I vilken ordning du lägger till villkoren är viktigt. Microsoft Entra utvärderar först alla villkor med källan Attribute
och utvärderar sedan alla villkor med källan Transformation
för att bestämma vilket värde som ska genereras i anspråket. Microsoft Entra ID utvärderar villkor med samma källa uppifrån och ned. Anspråket genererar det sista värdet som matchar uttrycket i anspråket. Transformeringar som IsNotEmpty
och Contains
fungerar som begränsningar.
Britta Simon är till exempel gästanvändare i Contoso-klientorganisationen. Britta tillhör en annan organisation som också använder Microsoft Entra-ID. Med följande konfiguration för Fabrikam-programmet utvärderar Microsofts identitetsplattform villkoren när Britta försöker logga in på Fabrikam.
Först kontrollerar Microsofts identitetsplattform om Brittas användartyp är Alla gäster. Eftersom typen är Alla gäster tilldelar Microsofts identitetsplattform källan för anspråket till user.extensionattribute1
. För det andra kontrollerar Microsofts identitetsplattform om Brittas användartyp är Microsoft Entra-gäster. Eftersom typen är Alla gäster tilldelar Microsofts identitetsplattform källan för anspråket till user.mail
. Slutligen genereras anspråket med värdet user.mail
för för Britta.
Som ett annat exempel bör du överväga när Britta Simon försöker logga in med hjälp av följande konfiguration. Microsoft Entra utvärderar först alla villkor med källan Attribute
. Källan för anspråket är user.mail
när Brittas användartyp är Microsoft Entra-gäster. Därefter utvärderar Microsoft Entra-ID omvandlingarna. Eftersom Britta är gäst user.extensionattribute1
är den nya källan för anspråket. Eftersom Britta finns i Microsoft Entra-gäster är user.othermail
den nya källan för det här anspråket. Slutligen genereras anspråket med värdet user.othermail
för för Britta.
Som ett sista exempel bör du tänka på vad som händer om Britta inte har konfigurerats user.othermail
eller om det är tomt. Anspråket återgår till att user.extensionattribute1
ignorera villkorsposten i båda fallen.
Säkerhetsfrågor
Program som tar emot token förlitar sig på anspråksvärden som inte kan manipuleras. När du ändrar tokeninnehållet via anspråksanpassning kanske dessa antaganden inte längre är korrekta. Program måste uttryckligen bekräfta att token har ändrats för att skydda sig mot anpassningar som skapats av skadliga aktörer. Skydda mot olämpliga anpassningar på något av följande sätt:
- Konfigurera en anpassad signeringsnyckel
- uppdatera programmanifestet för att acceptera mappade anspråk.
Utan detta returnerar Microsoft Entra-ID en AADSTS50146 felkod.
Konfigurera en anpassad signeringsnyckel
För appar med flera klientorganisationer ska en anpassad signeringsnyckel användas. Ange inte acceptMappedClaims
i appmanifestet. När du konfigurerar en app i Azure Portal får du ett appregistreringsobjekt och ett huvudnamn för tjänsten i klientorganisationen. Den appen använder den globala inloggningsnyckeln i Azure, som inte kan användas för att anpassa anspråk i token. Om du vill hämta anpassade anspråk i token skapar du en anpassad inloggningsnyckel från ett certifikat och lägger till den i tjänstens huvudnamn. I testsyfte kan du använda ett självsignerat certifikat. När du har konfigurerat den anpassade signeringsnyckeln måste programkoden verifiera tokensigneringsnyckeln.
Lägg till följande information i tjänstens huvudnamn:
- Privat nyckel (som en nyckelautentiseringsuppgift)
- Lösenord (som lösenordsautentiseringsuppgifter)
- Offentlig nyckel (som en nyckelautentiseringsuppgift)
Extrahera den privata och offentliga nyckeln base-64 som kodas från PFX-filexporten av certifikatet. Kontrollera att keyId
för det keyCredential
som används för "Sign" matchar keyId
passwordCredential
för . Du kan generera customkeyIdentifier
genom att hämta hashen för certifikatets tumavtryck.
Begär
Kommentar
Inaktivera först konfigurationen av tjänsthuvudnamnslås på nyligen skapade appar från bladet Appregistreringar i Microsoft Entra Administrationscenter innan du försöker göra en PATCH på tjänstens huvudnamn, vilket resulterar i en 400 felaktig begäran.
I följande exempel visas formatet för HTTP PATCH-begäran om att lägga till en anpassad signeringsnyckel i tjänstens huvudnamn. Värdet "nyckel" i egenskapen keyCredentials
förkortas för läsbarhet. Värdet är base-64-kodat. För den privata nyckeln är Sign
egenskapsanvändningen . För den offentliga nyckeln är Verify
egenskapsanvändningen .
PATCH https://graph.microsoft.com/v1.0/servicePrincipals/aaaaaaaa-bbbb-cccc-1111-222222222222
Content-type: servicePrincipals/json
Authorization: Bearer {token}
{
"keyCredentials":[
{
"customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
"endDateTime": "2021-04-22T22:10:13Z",
"keyId": "aaaaaaaa-0b0b-1c1c-2d2d-333333333333",
"startDateTime": "2020-04-22T21:50:13Z",
"type": "X509CertAndPassword",
"usage": "Sign",
"key":"cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
"displayName": "CN=contoso"
},
{
"customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
"endDateTime": "2021-04-22T22:10:13Z",
"keyId": "bbbbbbbb-1c1c-2d2d-3e3e-444444444444",
"startDateTime": "2020-04-22T21:50:13Z",
"type": "AsymmetricX509Cert",
"usage": "Verify",
"key": "cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
"displayName": "CN=contoso"
}
],
"passwordCredentials": [
{
"customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
"keyId": "cccccccc-2d2d-3e3e-4f4f-555555555555",
"endDateTime": "2022-01-27T19:40:33Z",
"startDateTime": "2020-04-20T19:40:33Z",
"secretText": "mypassword"
}
]
}
Konfigurera en anpassad signeringsnyckel med PowerShell
Använd PowerShell för att instansiera ett offentligt MSAL-klientprogram och använda flödet Bevilja auktoriseringskod för att hämta en delegerad behörighetsåtkomsttoken för Microsoft Graph. Använd åtkomsttoken för att anropa Microsoft Graph och konfigurera en anpassad signeringsnyckel för tjänstens huvudnamn. När du har konfigurerat den anpassade signeringsnyckeln måste programkoden verifiera tokensigneringsnyckeln.
Om du vill köra det här skriptet behöver du:
- Objekt-ID:t för programmets tjänsthuvudnamn finns på översiktsbladet för programmets post i Företagsprogram i Azure Portal.
- En appregistrering för att logga in en användare och få en åtkomsttoken för att anropa Microsoft Graph. Hämta appens program-ID (klient) på bladet Översikt för programmets post i Appregistreringar i Azure Portal. Appregistreringen bör ha följande konfiguration:
- En omdirigerings-URI för "http://localhost" i plattformskonfigurationen för mobil- och skrivbordsprogram .
- I API-behörigheter har Microsoft Graph delegerade behörigheter Application.ReadWrite.All och User.Read (se till att du ger administratörsmedgivande till dessa behörigheter).
- En användare som loggar in för att hämta Åtkomsttoken för Microsoft Graph. Användaren bör vara en av följande administrativa Roller för Microsoft Entra (krävs för att uppdatera tjänstens huvudnamn):
- Molnappadministratör
- Appadministratör
- Ett certifikat som ska konfigureras som en anpassad signeringsnyckel för vårt program. Du kan antingen skapa ett självsignerat certifikat eller hämta ett från din betrodda certifikatutfärdare. Följande certifikatkomponenter används i skriptet:
- offentlig nyckel (vanligtvis en .cer fil)
- privat nyckel i PKCS#12-format (i .pfx-fil )
- lösenord för den privata nyckeln (.pfx-filen )
Viktigt!
Den privata nyckeln måste vara i PKCS#12-format eftersom Microsoft Entra ID inte stöder andra formattyper. Om du använder fel format kan det resultera i felet "Ogiltigt certifikat: Nyckelvärdet är ogiltigt certifikat" när du använder Microsoft Graph för att KORRIGERA tjänstens huvudnamn med en keyCredentials
som innehåller certifikatinformationen.
##########################################################
# Replace the variables below with the appropriate values
$fqdn="yourDomainHere" # This is used for the 'issued to' and 'issued by' field of the certificate
$pwd="password" # password for exporting the certificate private key
$tenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee" # Replace with your Tenant ID
$appObjId = "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" # Replace with the Object ID of the App Registration
##########################################################
# Create a self-signed cert
$cert = New-SelfSignedCertificate -certstorelocation cert:\currentuser\my -DnsName $fqdn
$pwdSecure = ConvertTo-SecureString -String $pwd -Force -AsPlainText
$path = 'cert:\currentuser\my\' + $cert.Thumbprint
$location="C:\\temp" # path to folder where both the pfx and cer file will be written to
$cerFile = $location + "\\" + $fqdn + ".cer"
$pfxFile = $location + "\\" + $fqdn + ".pfx"
# Export the public and private keys
Export-PfxCertificate -cert $path -FilePath $pfxFile -Password $pwdSecure
Export-Certificate -cert $path -FilePath $cerFile
$pfxpath = $pfxFile # path to pfx file
$cerpath = $cerFile # path to cer file
$password = $pwd # password for the pfx file
# Check PowerShell version (minimum 5.1) (.Net) or PowerShell Core (.Net Core) and read the certificate file accordingly
if ($PSVersionTable.PSVersion.Major -gt 5)
{
$core = $true
}
else
{
$core = $false
}
# this is for PowerShell Core
$Secure_String_Pwd = ConvertTo-SecureString $password -AsPlainText -Force
# reading certificate files and creating Certificate Object
if ($core)
{
$pfx_cert = get-content $pfxpath -AsByteStream -Raw
$cer_cert = get-content $cerpath -AsByteStream -Raw
$cert = Get-PfxCertificate -FilePath $pfxpath -Password $Secure_String_Pwd
}
else
{
$pfx_cert = get-content $pfxpath -Encoding Byte
$cer_cert = get-content $cerpath -Encoding Byte
# calling Get-PfxCertificate in PowerShell 5.1 prompts for password - using alternative method
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxpath, $password)
}
# base 64 encode the private key and public key
$base64pfx = [System.Convert]::ToBase64String($pfx_cert)
$base64cer = [System.Convert]::ToBase64String($cer_cert)
# getting id for the keyCredential object
$guid1 = New-Guid
$guid2 = New-Guid
# get the custom key identifier from the certificate thumbprint:
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha256')
$hash = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($cert.Thumbprint))
$customKeyIdentifier = [System.Convert]::ToBase64String($hash)
# get end date and start date for our keycredentials
$endDateTime = ($cert.NotAfter).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
$startDateTime = ($cert.NotBefore).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
# building our json payload
$object = [ordered]@{
keyCredentials = @(
[ordered]@{
customKeyIdentifier = $customKeyIdentifier
endDateTime = $endDateTime
keyId = $guid1
startDateTime = $startDateTime
type = "AsymmetricX509Cert"
usage = "Sign"
key = $base64pfx
displayName = "CN=$fqdn"
},
[ordered]@{
customKeyIdentifier = $customKeyIdentifier
endDateTime = $endDateTime
keyId = $guid2
startDateTime = $startDateTime
type = "AsymmetricX509Cert"
usage = "Verify"
key = $base64cer
displayName = "CN=$fqdn"
}
)
passwordCredentials = @(
[ordered]@{
customKeyIdentifier = $customKeyIdentifier
displayName = "CN=$fqdn"
keyId = $guid1
endDateTime = $endDateTime
startDateTime = $startDateTime
secretText = $password
hint = $null
}
)
}
Connect-MgGraph -tenantId $tenantId -Scopes Application.ReadWrite.All
$graphuri = "https://graph.microsoft.com/v1.0/applications/$appObjId"
Invoke-MgGraphRequest -Method PATCH -Uri $graphuri -Body $object
$json = $object | ConvertTo-Json -Depth 99
Write-Host "JSON Payload:"
Write-Output $json
Verifiera tokensigneringsnyckel
Appar som har aktiverat anspråksmappning måste verifiera sina tokensigneringsnycklar genom att lägga appid={client_id}
till sina OpenID Connect-metadatabegäranden. I följande exempel visas formatet för det OpenID Connect-metadatadokument som du bör använda:
https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?appid={client-id}
Uppdatera programmanifestet
För appar för en enskild klientorganisation kan du ange acceptMappedClaims
egenskapen till true
i programmanifestet. Enligt beskrivningen i apiApplication
resurstypen. Om du anger egenskapen kan ett program använda anspråksmappning utan att ange en anpassad signeringsnyckel.
Varning
Ange inte egenskapen acceptMappedClaims till true för appar med flera klientorganisationer, vilket kan göra det möjligt för skadliga aktörer att skapa principer för anspråksmappning för din app.
Den begärda tokenpubliken måste använda ett verifierat domännamn för din Microsoft Entra-klientorganisation, vilket innebär att du bör ange Application ID URI
(representeras av identifierUris
i programmanifestet) till exempel till https://contoso.com/my-api
eller (helt enkelt med standardklientnamnet) https://contoso.onmicrosoft.com/my-api
.
Om du inte använder en verifierad domän returnerar Microsoft Entra-ID en AADSTS501461
felkod med meddelandet "_AcceptMappedClaims stöds endast för en tokenpublik som matchar programmets GUID eller en målgrupp inom klientorganisationens verifierade domäner. Ändra antingen resursidentifieraren eller använd en programspecifik signeringsnyckel."
Avancerade anspråksalternativ
Konfigurera avancerade anspråksalternativ för OIDC-program för att exponera samma anspråk som SAML-token. Även för program som tänker använda samma anspråk för både SAML2.0- och OIDC-svarstoken.
Konfigurera avancerade anspråksalternativ genom att markera kryssrutan under Avancerade anspråksalternativ på bladet Hantera anspråk .