Entra B2C Custom Policy – Trying to add Custom Claims for Sign Up that save to User Properties

I am trying to use the Sign up using invitation sample for B2C. We only want users to be able to sign up via invitation.

In my Entra B2C tenant, I have two User Attributes assigned:

  • AdvisorId
  • ClientId

I would like to persist these values on signup, and then return them as claims on sign in.

For my sign in user flow, I have already checked them to enable them as claims.

For generating my token, I have successfully added the claims and they look like this:


{
  ...
  "name": "Johnny Test",
  "https://schemas.mydomain.com/identity/advisorId": "12345",
  "https://schemas.mydomain.com/identity/client/clientId": "67890"
}

The problem is on the redeem script. What I need it to do is, using the script from the example as a base, modify it so the incoming claims are saved to the user attributes.

Where I am

I have added definitions for my claim and the attribute:


    <ClaimType Id="advisorId">
        <DisplayName>User's Advisor Id</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="https://schemas.mydomain.com/identity/advisorId"/>
        <Protocol Name="OpenIdConnect" PartnerClaimType="https://schemas.mydomain.com/identity/advisorId"/>
        <Protocol Name="SAML2" PartnerClaimType="https://schemas.mydomain.com/identity/advisorId"/>
        </DefaultPartnerClaimTypes>
        <UserHelpText>Advisor identifier (ID)</UserHelpText>
    </ClaimType>
    
    <ClaimType Id="clientId">
        <DisplayName>User's Client Id</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="https://schemas.mydomain.com/identity/client/clientId"/>
        <Protocol Name="OpenIdConnect" PartnerClaimType="https://schemas.mydomain.com/identity/client/clientId"/>
        <Protocol Name="SAML2" PartnerClaimType="https://schemas.mydomain.com/identity/client/clientId"/>
        </DefaultPartnerClaimTypes>
        <UserHelpText>Client identifier (ID)</UserHelpText>
    </ClaimType>
    
    <ClaimType Id="advisorIdAttribute">
        <DisplayName>User's Advisor Id</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="AdvisorId"/>
        </DefaultPartnerClaimTypes>
        <UserHelpText>Advisor identifier (ID)</UserHelpText>
    </ClaimType>
    
    <ClaimType Id="clientIdAttribute">
        <DisplayName>User's Client Id</DisplayName>
        <DataType>string</DataType>
        <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="ClientId"/>
        </DefaultPartnerClaimTypes>
        <UserHelpText>Client identifier (ID)</UserHelpText>
    </ClaimType>

Then, I have my mapping defined to translate from the claim to the attribute.


    <ClaimsTransformation Id="MapAdvisorIdClaimToUserAttribute" TransformationMethod="CopyClaim">
        <InputClaims>
            <InputClaim ClaimTypeReferenceId="advisorId" TransformationClaimType="inputClaim" />
        </InputClaims>
        <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="advisorIdAttribute" TransformationClaimType="outputClaim" />
        </OutputClaims>
    </ClaimsTransformation>
    
    <ClaimsTransformation Id="MapClientIdClaimToUserAttribute" TransformationMethod="CopyClaim">
        <InputClaims>
            <InputClaim ClaimTypeReferenceId="clientId" TransformationClaimType="inputClaim" />
        </InputClaims>
        <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="clientIdAttribute" TransformationClaimType="outputClaim" />
        </OutputClaims>
    </ClaimsTransformation>

Here’s the modified open id configuration


    <ClaimsProvider>
        <DisplayName>Self Referenced ID Token Hint ClaimsProvider</DisplayName>
        <TechnicalProfiles>
            <TechnicalProfile Id="IdTokenHint_ExtractClaims">
                <DisplayName>Self referenced ID Token Hint TechnicalProfile</DisplayName>
                <Protocol Name="None" />
                <Metadata>
                    <Item Key="METADATA">https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/B2C_1A_INV_redeem/v2.0/.well-known/openid-configuration</Item>
                </Metadata>
                <OutputClaims>
                    <!-- claims to read from the id_token_hint-->
                    <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="sub"/>
                    <OutputClaim ClaimTypeReferenceId="displayName" PartnerClaimType="name"/>
                    <OutputClaim ClaimTypeReferenceId="advisorId" PartnerClaimType="https://schemas.mydomain.com/identity/advisorId"/>
                    <OutputClaim ClaimTypeReferenceId="clientId" PartnerClaimType="https://schemas.mydomain.com/identity/client/clientId"/>
                </OutputClaims>
            </TechnicalProfile>
        </TechnicalProfiles>
    </ClaimsProvider>

And then at the bottom where the comments say to define the claims on the token, I have the following:


    <RelyingParty>
        <DefaultUserJourney ReferenceId="SignInWithIdTokenHint" />
        <UserJourneyBehaviors>
            <JourneyInsights TelemetryEngine="ApplicationInsights" InstrumentationKey="111...111" DeveloperMode="true" ClientEnabled="true" ServerEnabled="true" TelemetryVersion="1.0.0" />
            <ScriptExecution>Allow</ScriptExecution>
        </UserJourneyBehaviors>
        <TechnicalProfile Id="PolicyProfile">
            <DisplayName>PolicyProfile</DisplayName>
            <Protocol Name="OpenIdConnect" />
            <!--Sample: Set the input claims to be read from the id_token_hint-->
            <InputClaims>
                <InputClaim ClaimTypeReferenceId="email" />
                <InputClaim ClaimTypeReferenceId="displayName" />
            </InputClaims>
            <OutputClaims>
                <OutputClaim ClaimTypeReferenceId="displayName" />
                <OutputClaim ClaimTypeReferenceId="givenName" />
                
                <!--
        <OutputClaim ClaimTypeReferenceId="surname" />
        <OutputClaim ClaimTypeReferenceId="email" />
        -->
                <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
                <OutputClaim ClaimTypeReferenceId="advisorId" PartnerClaimType="https://schemas.mydomain.com/identity/advisorId"/>
                <OutputClaim ClaimTypeReferenceId="clientId" PartnerClaimType="https://schemas.mydomain.com/identity/client/clientId"/>
                <OutputClaim ClaimTypeReferenceId="tenantId" AlwaysUseDefaultValue="true" DefaultValue="{Policy:TenantObjectId}" />
            </OutputClaims>
            <SubjectNamingInfo ClaimType="sub" />
        </TechnicalProfile>
    </RelyingParty>

Here’s where I’m having the issue. I’m trying to get those claims to map so they save to the user attributes. Here’s my modifications.


    <ClaimsProvider>
        <DisplayName>Local Account</DisplayName>
        <TechnicalProfiles>
            <!-- Self Asserted page for Signup from an email invite and id_token_hint -->
            <TechnicalProfile Id="LocalAccountSignUpFromEmailInvite">
                <DisplayName>Email signup</DisplayName>
                <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <Metadata>
                    <Item Key="IpAddressClaimReferenceId">IpAddress</Item>
                    <Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
                    <Item Key="language.button_continue">Signup</Item>
                    <Item Key="setting.showCancelButton">false</Item>
                </Metadata>
                <CryptographicKeys>
                    <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
                </CryptographicKeys>
                <InputClaimsTransformations>
                    <InputClaimsTransformation ReferenceId="CopyEmailAddress" />
                </InputClaimsTransformations>
                <InputClaims>
                    <InputClaim ClaimTypeReferenceId="ReadOnlyEmail" />
                    <InputClaim ClaimTypeReferenceId="displayName" />
                </InputClaims>
                <OutputClaims>
                    <OutputClaim ClaimTypeReferenceId="objectId" />
                    <OutputClaim ClaimTypeReferenceId="ReadOnlyEmail" Required="true" />
                    <OutputClaim ClaimTypeReferenceId="displayName" />
                    <OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
                    <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
                    <OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
                    <OutputClaim ClaimTypeReferenceId="advisorIdAttribute" />
                    <OutputClaim ClaimTypeReferenceId="clientIdAttribute" />
                </OutputClaims>
                <OutputClaimsTransformations>
                    <OutputClaimsTransformation ReferenceId="MapAdvisorIdClaimToUserAttribute" />
                    <OutputClaimsTransformation ReferenceId="MapClientIdClaimToUserAttribute" />
                </OutputClaimsTransformations>
                <ValidationTechnicalProfiles>
                    <ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
                    <!-- write the user object to the directory -->
                    <!-- <ValidationTechnicalProfile ReferenceId="SendSignupEvent" /> -->
                    <!-- notify backend system of user creation -->
                </ValidationTechnicalProfiles>
                <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
            </TechnicalProfile>
        </TechnicalProfiles>
    </ClaimsProvider>

When I try to upload the policy, I get the following error:

Claim Type “advisorId” is the output claim of the relying party’s technical profile, but it is not an output claim in any of the steps of user journey “SignInWithIdTokenHint”.

I get the same error for client id.

The claims are defined as the output of IdTokenHint_ExtractClaims as you can see above, and the user journey is unchanged:



    <UserJourneys>
        <!-- UserJourney to redeem the email invite. It uses id_token_hint to validate the id_token passed -->
        <UserJourney Id="SignInWithIdTokenHint">
            <OrchestrationSteps>
                <!-- Read the input claims from the id_token_hint-->
                <OrchestrationStep Order="1" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />

    ...

What am I missing in order to get this to pass verification, and what am I missing to get the two claims to save into user attributes?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật