Azure AD B2C - "emails" claim in custom policy
Asked Answered
F

2

12

I'm looking for a way to add an emails claim (collection of emails) to a custom policy for Azure AD B2C. This application claim is available from the Azure Portal directly but I cannot find a way to implement this in a custom policy which I need to create.

What I want to achieve is to have Azure AD B2C authentication for my WebApp users and Azure AD authentication as custom Authentication Provider for employees so It means I will need to add emails claim twice - for Local accounts and for Azure AD.

I followed this guide to make custom policy so I've added a new ClaimsProvider to TrustFrameworkExtensions.xml file.

When I download Sign Up & Sign In policy created in Azure Portal then I can see the following Output Claim:

<OutputClaim ClaimTypeReferenceId="emails" />

I tried to put that line to my custom policy but it does not return emails claim.

Any ideas?

Flying answered 16/10, 2017 at 19:58 Comment(2)
Where are you trying to get the email address from before putting it in the token? Is it a Rest API, or just a local account sign-in? If you have a new technical profile, then it will be good to add that in the question. Otherwise, mention the starter pack and your scenario.Afternoons
This post doesn't work, this one does.Reich
B
12

I couldn't find an answer this either - it looks like the "emails" claim is being returned by a custom OutputClaimsTransformation, the configuration of which isn't available in the samples.

I did find the this answer on SO which helped, but it covers updated the "otherMails" claim for NEW users and I had existing users on the basic policies who I couldn't update in that way.

It seems that emails is being populated by concatenating "otherMails" (in the case of social signups) with the first entry in the "signInNames" array.

I ended up doing the following to get the "emails" claim dynamically created.

Create two new ClaimTypes in TrustFrameworkExtensions.xml

  <ClaimType Id="emails">
    <DisplayName>Emails</DisplayName>
    <DataType>stringCollection</DataType>
    <UserHelpText>User's email addresses</UserHelpText>
  </ClaimType>

 <ClaimType Id="firstOtherMail">
    <DisplayName>First Other mail</DisplayName>
    <DataType>string</DataType>
    <UserHelpText>Other Mail</UserHelpText>
  </ClaimType>

Create 3 new ClaimsTransformations in TrustFrameworkExtensions.xml

<ClaimsTransformation Id="GetFirstOtherMail" TransformationMethod="GetSingleItemFromStringCollection">
    <InputClaims>
      <InputClaim ClaimTypeReferenceId="otherMails" TransformationClaimType="collection" />
    </InputClaims>
    <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="firstOtherMail" TransformationClaimType="extractedItem" />
    </OutputClaims>
  </ClaimsTransformation>

  <ClaimsTransformation Id="CopyFirstOtherMailToEmail" TransformationMethod="AddItemToStringCollection">
    <InputClaims>
      <InputClaim ClaimTypeReferenceId="firstOtherMail" TransformationClaimType="item" />
      <InputClaim ClaimTypeReferenceId="emails" TransformationClaimType="collection" />
    </InputClaims>
    <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="emails" TransformationClaimType="collection" />
    </OutputClaims>
  </ClaimsTransformation>

  <ClaimsTransformation Id="CopySignInNamesEmailToEmails" TransformationMethod="AddItemToStringCollection">
    <InputClaims>
      <InputClaim ClaimTypeReferenceId="signInNames.emailAddress" TransformationClaimType="item" />
      <InputClaim ClaimTypeReferenceId="emails" TransformationClaimType="collection" />
    </InputClaims>
    <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="emails" TransformationClaimType="collection" />
    </OutputClaims>
  </ClaimsTransformation>

Create a new TechnicalProfile in TrustFrameworkExtensions.xml:

<!-- The following technical profile is used to create the emails collection after user authenticates. -->
    <TechnicalProfile Id="AAD-UserCreateEmailsClaim">
      <Metadata>
        <Item Key="Operation">Read</Item>
        <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
      </Metadata>
      <IncludeInSso>false</IncludeInSso>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="objectId" Required="true" />
      </InputClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emails" />           
      </OutputClaims>
      <OutputClaimsTransformations>
        <OutputClaimsTransformation ReferenceId="GetFirstOtherMail"/>
        <OutputClaimsTransformation ReferenceId="CopySignInNamesEmailToEmails"/>
        <OutputClaimsTransformation ReferenceId="CopyFirstOtherMailToEmail"/>
      </OutputClaimsTransformations>
      <IncludeTechnicalProfile ReferenceId="AAD-Common" />
    </TechnicalProfile>

Add a new OrchestrationStep to the SignUpOrSignIn UserJourney just before the last step (SendClaims) in SignUpOrSignIn

    <OrchestrationStep Order="8" Type="ClaimsExchange">
      <ClaimsExchanges>
        <!-- create the emails claim combining signInNames and otherMails -->
        <ClaimsExchange Id="AADUserCreateEmailsClaim" TechnicalProfileReferenceId="AAD-UserCreateEmailsClaim" />
      </ClaimsExchanges>
    </OrchestrationStep>


    <OrchestrationStep Order="9" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

Edit the PolicyProfile TechnicalProfile and add the OutputClaim:

 <OutputClaim ClaimTypeReferenceId="emails" />
Buttons answered 26/2, 2018 at 16:33 Comment(5)
You're a life saver!Geoffreygeoffry
Policy "..." of tenant "..." makes a reference to ClaimType with id "firstOtherMail" but neither the policy nor any of its base policies contain such an element...Laywoman
Apologies, i missed that one out - see amended answer.Buttons
@Buttons this doesn't work with Multitenant Azure Active directory integration to B2C. Do you have any idea why?Schmaltzy
@Buttons Thanks for the clear and precise answer. In my case the SignInSignUp.xml custom policy was throwing the error while uploading. Actually, the "emails" claim does not exist in user object.So, updating the technical profile as per this : #56195093 helped meHoopoe
X
8

I took a much simpler route, and just added the following output claim in the SignInSignUp.xml (I left the existing email output claim in, that anyway gets populated only for social sign-ins)

<OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" PartnerClaimType="email" />
Xeric answered 13/1, 2020 at 8:16 Comment(2)
this did nothing for me was there more to add?Airminded
this works for google, facebook. but apple send email claim as emails.Ideogram

© 2022 - 2024 — McMap. All rights reserved.