Définir un profil technique id_token_hint dans une stratégie personnalisée Azure Active Directory B2C

Azure AD B2C permet aux applications par partie de confiance d’envoyer un jeton JWT entrant dans le cadre de la demande d’autorisation OAuth2. Le jeton JWT peut être émis par une application de partie de confiance ou un fournisseur d’identité, et il peut transmettre une indication sur l’utilisateur ou la demande d’autorisation. Azure AD B2C valide la signature, le nom de l’émetteur et l’audience du jeton, puis extrait la revendication du jeton entrant.

Cas d'utilisation

Vous pouvez utiliser cette solution pour envoyer des données à Azure AD B2C encapsulées dans un jeton JWT unique. La solution Signup with email invitation, où votre administrateur système peut envoyer une invitation signée à des utilisateurs, est basée sur id_token_hint. Seuls les utilisateurs ayant accès à l’e-mail d’invitation peuvent créer le compte dans le répertoire.

Approche de signature de jetons

Avec id_token_hint, l’émetteur de jeton (une application de partie de confiance ou un fournisseur d’identité) compose le jeton, puis le signe à l’aide d’une clé de signature pour prouver que le jeton provient d’une source approuvée. La clé de signature peut être symétrique ou asymétrique. Le chiffrement symétrique, ou chiffrement à clé privée, utilise un secret partagé pour signer et valider la signature. Le chiffrement asymétrique, ou chiffrement à clé publique, est un système de chiffrement qui utilise à la fois une clé privée et une clé publique. La clé privée est connue uniquement de l’émetteur de jeton et est utilisée pour signer le jeton. La clé publique est partagée avec la stratégie Azure AD B2C pour valider la signature du jeton.

Format de jeton

id_token_hint doit être un jeton JWT valide. Le tableau suivant répertorie les revendications qui sont obligatoires. Les revendications supplémentaires sont facultatives.

Name Revendication Valeur d'exemple Description
Public visé aud a489fc44-3cc0-4a78-92f6-e413cd853eae Identifie le destinataire du jeton. L’audience est une chaîne arbitraire définie par l’émetteur du jeton. Azure AD B2C valide cette valeur et rejette le jeton si elle ne correspond pas.
Émetteur iss https://localhost Identifie le service de jeton de sécurité (émetteur de jeton). L’émetteur est un URI arbitraire défini par l’émetteur du jeton. Azure AD B2C valide cette valeur et rejette le jeton si elle ne correspond pas.
Heure d’expiration exp 1600087315 Heure à laquelle le jeton n’est plus valide, représentée en heure epoch. Azure AD B2C valide cette valeur et rejette le jeton s’il a expiré.
Pas avant nbf 1599482515 Heure à laquelle le jeton est valide, représentée en heure epoch. Cette heure correspond généralement à l’heure à laquelle le jeton a été émis. Azure AD B2C valide cette valeur et rejette le jeton si sa durée de vie n’est pas valide.

Le jeton suivant est un exemple de jeton d’ID valide :

{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "displayName": " John Smith",
  "userId": "john.s@contoso.com",
  "nbf": 1599482515,
  "exp": 1600087315,
  "iss": "https://localhost",
  "aud": "a489fc44-3cc0-4a78-92f6-e413cd853eae"
}

Protocol

L’attribut Name de l’élément Protocol doit être défini sur None. Par exemple, le protocole pour le profil technique IdTokenHint_ExtractClaims est None :

<TechnicalProfile Id="IdTokenHint_ExtractClaims">
  <DisplayName> My ID Token Hint TechnicalProfile</DisplayName>
  <Protocol Name="None" />
  ...

Le profil technique est appelé à partir d’une étape d’orchestration avec le type de GetClaims.

<OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />

Revendications de sortie

L’élément OutputClaims contient une liste de revendications à extraire du jeton JWT. Il se peut que vous deviez mapper le nom de la revendication définie dans votre stratégie au nom défini dans le jeton JWT. Vous pouvez également inclure des revendications qui ne sont pas retournées par le jeton JWT, pour autant que vous définissiez l’attribut DefaultValue.

Métadonnées

Les métadonnées suivantes sont pertinentes lors de l’utilisation d’une clé symétrique.

Attribut Obligatoire Description
émetteur Oui Identifie le service de jeton de sécurité (émetteur de jeton). Cette valeur doit être identique à la revendication iss dans la revendication de jeton JWT.
IdTokenAudience Oui Identifie le destinataire du jeton. Doit être identique à la revendication aud dans la revendication de jeton JWT.

Les métadonnées suivantes sont pertinentes lors de l’utilisation d’une clé asymétrique.

Attribut Obligatoire Description
METADATA Oui URL qui pointe vers un document de configuration d’émetteur de jeton, également appelé point de terminaison de configuration OpenID connu.
émetteur Non Identifie le service de jeton de sécurité (émetteur de jeton). Cette valeur peut être utilisée pour remplacer la valeur configurée dans les métadonnées et doit être identique à la revendication iss dans la revendication de jeton JWT.
IdTokenAudience Non Identifie le destinataire du jeton. Doit être identique à la revendication aud dans la revendication de jeton JWT.

Important

Vos points de terminaison doivent respecter les exigences d’Azure AD B2C en matière de sécurité. Les versions et les chiffrements TLS antérieurs sont déconseillés. Pour plus d’informations, consultez Configuration requise pour TLS et les suites de chiffrement Azure AD B2C.

Clés de chiffrement

Lors de l’utilisation d’une clé symétrique, l’élément CryptographicKeys contient l’attribut suivant :

Attribut Obligatoire Description
client_secret Oui Clé de chiffrement utilisée pour valider la signature du jeton JWT.

Guide pratique

Émettre un jeton avec des clés symétriques

Étape 1 : créer une clé partagée

Créez une clé qui peut être utilisée pour signer le jeton. Par exemple, utilisez le code PowerShell suivant pour générer une clé.

$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$rand.Dispose()
$newClientSecret = [System.Convert]::ToBase64String($bytes)
$newClientSecret

Ce code crée une chaîne secrète comme VK62QTn0m1hMcn0DQ3RPYDAr6yIiSvYgdRwjZtU5QhI=.

Étape 2 : ajouter la clé de signature à Azure AD B2C

La clé utilisée par l’émetteur de jeton doit être créée dans vos clés de stratégie Azure AD B2C.

  1. Connectez-vous au portail Azure.
  2. Si vous avez accès à plusieurs locataires, sélectionnez l’icône Paramètres dans le menu supérieur pour basculer vers votre locataire Azure AD B2C à partir du menu Annuaires + abonnements.
  3. Dans la Portail Azure, recherchez et sélectionnez Azure AD B2C.
  4. Dans la page de vue d’ensemble, sous Stratégies, sélectionnez Identity Experience Framework.
  5. Sélectionner Clés de stratégie
  6. Sélectionnez Manuel.
  7. Pour Nom, utilisez IdTokenHintKey.
    Il est possible que le préfixe B2C_1A_ soit ajouté automatiquement.
  8. Dans la zone Secret, entrez la clé de connexion que vous avez générée précédemment.
  9. Pour Utilisation de la clé, utilisez Chiffrement.
  10. Sélectionnez Create (Créer).
  11. Vérifiez que vous avez créé la clé B2C_1A_IdTokenHintKey.

Étape 3 : ajouter le profil technique du conseil de jeton d’ID

Le profil technique suivant valide le jeton et extrait les revendications.

<ClaimsProvider>
  <DisplayName>My ID Token Hint ClaimsProvider</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="IdTokenHint_ExtractClaims">
      <DisplayName> My ID Token Hint TechnicalProfile</DisplayName>
      <Protocol Name="None" />
      <Metadata>
        <Item Key="IdTokenAudience">a489fc44-3cc0-4a78-92f6-e413cd853eae</Item>
        <Item Key="issuer">https://localhost</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="client_secret" StorageReferenceId="B2C_1A_IdTokenHintKey" />
      </CryptographicKeys>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="userId" />
      </OutputClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

Étape 4 : préparer votre stratégie

Effectuez l’étape Configurer votre stratégie.

Étape 5 : préparer le code

L’exemple GitHub est une application web ASP.NET et une application console qui génère un jeton d’ID signé à l’aide d’une clé symétrique.

Émettre un jeton avec des clés asymétriques

Avec une clé asymétrique, le jeton est signé à l’aide de certificats RSA. Cette application héberge un point de terminaison de métadonnées OpenID Connect et un point de terminaison de clés web JSON (JWK) qui est utilisé par Azure AD B2C pour valider la signature du jeton d’ID.

L’émetteur de jeton doit fournir les points de terminaison suivants :

  • /.well-known/openid-configuration : un point de terminaison de configuration bien connu avec des informations pertinentes sur le jeton, comme le nom de l’émetteur du jeton et le lien vers le point de terminaison JWK.
  • /.well-known/keys : le point de terminaison de la clé web JSON (JWK) avec la clé publique utilisée pour signer la clé (avec la partie clé privée du certificat).

Consultez l’exemple de contrôleur MVC .NET TokenMetadataController.cs.

Étape 1 : préparer un certificat auto-signé

Si vous n’avez pas encore de certificat, vous pouvez utiliser un certificat auto-signé pour ce guide pratique. Sur Windows, vous pouvez utiliser l’applet de commande New-SelfSignedCertificate de PowerShell pour générer un certificat.

Exécutez cette commande PowerShell pour générer un certificat auto-signé. Modifiez l’argument -Subject comme il convient pour votre application et le nom de locataire Azure AD B2C. Vous pouvez également ajuster la date de -NotAfter pour spécifier un délai d’expiration différent pour le certificat.

New-SelfSignedCertificate `
    -KeyExportPolicy Exportable `
    -Subject "CN=yourappname.yourtenant.onmicrosoft.com" `
    -KeyAlgorithm RSA `
    -KeyLength 2048 `
    -KeyUsage DigitalSignature `
    -NotAfter (Get-Date).AddMonths(12) `
    -CertStoreLocation "Cert:\CurrentUser\My"

Étape 2 : ajouter le profil technique du conseil de jeton d’ID

Le profil technique suivant valide le jeton et extrait les revendications. Remplacez l’URI des métadonnées par le point de terminaison de configuration bien connu de votre émetteur de jeton.

<ClaimsProvider>
  <DisplayName>My ID Token Hint ClaimsProvider</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="IdTokenHint_ExtractClaims">
      <DisplayName> My ID Token Hint TechnicalProfile</DisplayName>
      <Protocol Name="None" />
      <Metadata>
        <!-- Replace with your endpoint location -->
        <Item Key="METADATA">https://your-app.azurewebsites.net/.well-known/openid-configuration</Item>
        <Item Key="IdTokenAudience">your_optional_audience</Item>
        <!-- <Item Key="issuer">your_optional_token_issuer_override</Item> -->
      </Metadata>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="userId" />
      </OutputClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

Étape 3 : préparer votre stratégie

Effectuez l’étape Configurer votre stratégie.

Étape 4 : préparer le code

Cet exemple GitHub d’application web ASP.NET génère des jetons d’ID et héberge les points de terminaison de métadonnées requis pour utiliser le paramètre « id_token_hint » dans Azure AD B2C.

Configurer votre stratégie

Pour les approches symétriques et asymétriques, le profil technique id_token_hint est appelé à partir d’une étape d’orchestration avec le type GetClaims et doit spécifier les revendications d’entrée de la stratégie de partie de confiance.

  1. Ajoutez le profil technique IdTokenHint_ExtractClaims à votre stratégie d’extension.

  2. Ajoutez l’étape d’orchestration suivante à votre parcours utilisateur en tant que premier élément.

    <OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />
    
  3. Dans votre stratégie de partie de confiance, répétez les mêmes revendications d’entrée que celles que vous avez configurées dans le profil technique IdTokenHint_ExtractClaims. Par exemple :

    <RelyingParty>
      <DefaultUserJourney ReferenceId="SignUp" />
      <TechnicalProfile Id="PolicyProfile">
        <DisplayName>PolicyProfile</DisplayName>
        <Protocol Name="OpenIdConnect" />
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="userId" />
        </InputClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="displayName" />
          <OutputClaim ClaimTypeReferenceId="givenName" />
          <OutputClaim ClaimTypeReferenceId="surname" />
          <OutputClaim ClaimTypeReferenceId="email" />
          <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>
          <OutputClaim ClaimTypeReferenceId="identityProvider" />
        </OutputClaims>
        <SubjectNamingInfo ClaimType="sub" />
      </TechnicalProfile>
    </RelyingParty>
    

En fonction des besoins de votre entreprise, vous devrez peut-être ajouter des validations de jeton, par exemple pour vérifier le format de l’adresse email. Pour ce faire, ajoutez des étapes d’orchestration qui appellent un profil technique de transformation des revendications. Ajoutez également un profil technique autodéclaré pour présenter un message d’erreur.

Créer et signer un jeton

Les exemples GitHub illustrent comment créer un tel jeton JWT qui est envoyé par la suite en tant que paramètre de chaîne de requête id_token_hint. Voici un exemple de demande d’autorisation avec un paramètre id_token_hint

https://tenant-name.b2clogin.com/tenant-name.onmicrosoft.com/B2C_1A_signup_signin/oauth2/v2.0/authorize?client_id=63ba0d17-c4ba-47fd-89e9-31b3c2734339&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid&response_type=id_token&prompt=login&id_token_hint=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkaXNwbGF5TmFtZSI6IiBKb2huIFNtaXRoIiwidXNlcklkIjoiam9obi5zQGNvbnRvc28uY29tIiwibmJmIjoxNTk5NDgyNTE1LCJleHAiOjE2MDAwODczMTUsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0IiwiYXVkIjoiYTQ4OWZjNDQtM2NjMC00YTc4LTkyZjYtZTQxM2NkODUzZWFlIn0.nPmLXydI83PQCk5lRBYUZRu_aX58pL1khahHyQuupig

Étapes suivantes