Custom attribute is not added to id_token in AAD B2C

SamD 151 Reputation points
2021-01-26T11:21:51.92+00:00

In Azure AD B2C I want to add an custom attribute called companyName for each user account and I'm using custom policies.

I referred following documentations:

Then added the user attribute in my AAD B2C instance via the portal:

60498-image.png

Then defined a claim in TrustFrameworkExtensions.xml as below:

    <ClaimType Id="extension_companyName">  
      <DisplayName>Company</DisplayName>  
      <DataType>string</DataType>  
      <UserHelpText>Please provide the name of your company</UserHelpText>  
      <UserInputType>TextBox</UserInputType>  
    </ClaimType>  

Then in the same extension file added following claim providers. (Please note that actual ClientId and ApplicationObjectId are removed here)

<ClaimsProviders>  
  <ClaimsProvider>  
    <DisplayName>Azure Active Directory</DisplayName>  
    <TechnicalProfiles>  
      <TechnicalProfile Id="AAD-Common">  
        <Metadata>  
          <!--Insert b2c-extensions-app application ID here, for example: 11111111-1111-1111-1111-111111111111-->  
          <Item Key="ClientId">11111111-1111-1111-1111-111111111111</Item>  
          <!--Insert b2c-extensions-app application ObjectId here, for example: 22222222-2222-2222-2222-222222222222-->  
          <Item Key="ApplicationObjectId">22222222-2222-2222-2222-222222222222</Item>  
        </Metadata>  
      </TechnicalProfile>  
      <!-- Write data during a federated account first-time sign-in flow. -->  
      <TechnicalProfile Id="AAD-UserWriteUsingAlternativeSecurityId">  
        <PersistedClaims>  
          <PersistedClaim ClaimTypeReferenceId="extension_companyName" DefaultValue="unknown" />  
        </PersistedClaims>  
      </TechnicalProfile>  
      <!-- Write data during edit profile flow. -->  
      <TechnicalProfile Id="AAD-UserWriteProfileUsingObjectId">  
        <PersistedClaims>  
          <PersistedClaim ClaimTypeReferenceId="extension_companyName" DefaultValue="unknown"/>  
        </PersistedClaims>  
      </TechnicalProfile>  
      <!-- Read data after user authenticates with a federated account. -->  
      <TechnicalProfile Id="AAD-UserReadUsingObjectId">  
        <OutputClaims>  
          <OutputClaim ClaimTypeReferenceId="extension_companyName"  DefaultValue="unknown"/>  
        </OutputClaims>  
      </TechnicalProfile>  
    </TechnicalProfiles>  
  </ClaimsProvider>  
 <ClaimsProvider>  
      <DisplayName>Self Asserted</DisplayName>  
    <TechnicalProfiles>  
        
      <TechnicalProfile Id="SelfAsserted-Social">  
        <OutputClaims>  
          <OutputClaim ClaimTypeReferenceId="extension_companyName"/>  
        </OutputClaims>  
      </TechnicalProfile>  
  
      <TechnicalProfile Id="SelfAsserted-ProfileUpdate">  
        <OutputClaims>  
          <OutputClaim ClaimTypeReferenceId="extension_companyName"/>  
        </OutputClaims>  
      </TechnicalProfile>  
  
    </TechnicalProfiles>  
  </ClaimsProvider>  
</ClaimsProviders>  

Then RelyingParty is as follow:

<RelyingParty>  
    <DefaultUserJourney ReferenceId="SignUpOrSignIn" />  
    <TechnicalProfile Id="PolicyProfile">  
      <DisplayName>PolicyProfile</DisplayName>  
      <Protocol Name="OpenIdConnect" />  
      <OutputClaims>  
        <OutputClaim ClaimTypeReferenceId="displayName" />  
        <OutputClaim ClaimTypeReferenceId="givenName" />  
        <OutputClaim ClaimTypeReferenceId="surname" />  
        <OutputClaim ClaimTypeReferenceId="email" />  
        <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>  
        <OutputClaim ClaimTypeReferenceId="identityProvider" />  
        <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />  
        <OutputClaim ClaimTypeReferenceId="extension_companyName" DefaultValue="unknown-from-RP" />  
      </OutputClaims>  
      <SubjectNamingInfo ClaimType="sub" />  
    </TechnicalProfile>  
  </RelyingParty>  

For the time being I'm using Google to authenticate users. When user is login for the first time(sign up), id_token contains the extension_companyName attribute and it contains the value provided by the user.
But when that use login for the next time, value of the extension_companyName attribute is unknown-from-RP. Which is the value I have mentioned as the DefaultValue in RelyingParty. But ideally it should be the value provided by the user during the signup. Could you help me to get this work? :)

Microsoft Entra External ID
Microsoft Entra External ID
A modern identity solution for securing access to customer, citizen and partner-facing apps and services. It is the converged platform of Azure AD External Identities B2B and B2C. Replaces Azure Active Directory External Identities.
2,677 questions
0 comments No comments
{count} vote

Accepted answer
  1. SamD 151 Reputation points
    2021-05-03T08:16:57.093+00:00

    I was able to fix this by adding following TechnicalProfile.

    <TechnicalProfile Id="AAD-UserReadUsingAlternativeSecurityId">
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="extension_companyName" DefaultValue="unknown-AAD-UserReadUsingAlternativeSecurityId" />
      </OutputClaims>
    </TechnicalProfile>
    
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. AmanpreetSingh-MSFT 56,316 Reputation points
    2021-01-27T13:13:59.817+00:00

    Hi @SamD · Thank you for reaching out.

    You need to first extend Azure AD schema of the B2C tenant with extension_companyName attribute using b2c-extensions-app. The document you are referring to, is with example of City attribute, which is by default present in Azure AD Schema.

    Please follow below steps to extend the Azure AD Schema of your B2C tenant with companyName attribute:

    1. Navigate to Azure Portal > Azure Active Directory > App Registration.
    2. Locate the b2c-extensions-app and copy the Object ID of the b2c-extensions-app.
    3. Open Graph Explorer by using https://developer.microsoft.com/en-us/graph/graph-explorer# url.
    4. Click on Sign in with Microsoft on the left and Sign in with Global Admin account who is a member of same directory and not added as external (guest) user.
    5. Click on Modify permissions > select Directory.AccessAsUser.All > click Modify Permissions.
    6. Click on Accept at consent page.
    7. In Graph Explorer, use following query. Where the < Tenant Name > is your_tenant.onmicrosoft.com in your case and < ObjectID of the application > is the value copied in Step 2.
      POST https://graph.microsoft.com/beta/< Tenant Name >/applications/< ObjectID of the application >/extensionProperties
    8. Use following text in the Request body. Since the targetObject is user, the attribute will be created for all Users in the tenant. Note: Please type the request body manually as with copy-paste Graph Explorer will not recognize some of the characters.
      {
      “name”: “companyName”,
      “dataType”: “String”,
      “targetObjects”: [“User”]
      }

    Optionally, to verify if the attribute is created in the directory and a value can be populated in the attribute, follow below steps. These steps are not needed in your case as the attribute value will be populated

    1. To update the attribute with a value use following query:
      PATCH https://graph.microsoft.com/beta/users/your_globaladmin@your_tenant.onmicrosoft.com
      And use following Request Body:
      {
      "extension_e175b1fc21b144019cadxxxxxxxxxxxx_companyName":"Value_to_be_assigned"
      }
    2. To verify if the attribute is updated successfully run following query:
      GET https://graph.microsoft.com/beta/users/ < User’s UPN or Object ID >

    -----------------------------------------------------------------------------------------------------------

    Please "Accept the answer" if the information provided helped you. This will help us and others in the community as well.

    1 person found this answer helpful.