2

Continuing from Populate the email address text box in Azure AD B2C Orchestration something has gone wrong. The email box is not populating and I am missing something. Idea is to verify a login with Email OTP and then let then change/add Mobile number for MFA

UserJourney

            <UserJourney Id="TestEmailOTP">
        <OrchestrationSteps>   
            <OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections">
                <ClaimsProviderSelections>
                    <ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
                </ClaimsProviderSelections>
            </OrchestrationStep>   
            <OrchestrationStep Order="2" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
                </ClaimsExchanges>
            </OrchestrationStep>
            <OrchestrationStep Order="3" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
                </ClaimsExchanges>
            </OrchestrationStep>    
            <OrchestrationStep Order="4" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="VerifyWithEmailOTP" TechnicalProfileReferenceId="LocalAccountDiscoveryUsingEmailAddressEmailOTP" />
                </ClaimsExchanges>
            </OrchestrationStep>
            <OrchestrationStep Order="5" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="NewPhoneFactor" TechnicalProfileReferenceId="PhoneFactor-EditAndVerify" />
                </ClaimsExchanges>
            </OrchestrationStep>   
            <OrchestrationStep Order="6" Type="ClaimsExchange">
                <ClaimsExchanges>
                    <ClaimsExchange Id="AADUserWriteWithObjectId" TechnicalProfileReferenceId="AAD-UserWritePhoneNumberUsingObjectId" />
                </ClaimsExchanges>
            </OrchestrationStep>   
            <OrchestrationStep Order="7" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
        </OrchestrationSteps>
        <ClientDefinition ReferenceId="DefaultWeb" />
    </UserJourney>

Technical Profile

    <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddressEmailOTP">
      <DisplayName>Reset password using email address</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.localaccountpasswordreset</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
      </CryptographicKeys>
      <IncludeInSso>false</IncludeInSso>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="readonlyEmail" />
        <OutputClaim ClaimTypeReferenceId="objectId" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
      </OutputClaims>
      <ValidationTechnicalProfiles>
        <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
        <ValidationTechnicalProfile ReferenceId="SelfAsserted-LocalAccount-EmailVerification" />
      </ValidationTechnicalProfiles>
    </TechnicalProfile>

AAD-UserReadUsingEmailAddress

        <TechnicalProfile Id="AAD-UserReadUsingEmailAddress">
          <Metadata>
            <Item Key="Operation">Read</Item>
            <Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
            <Item Key="UserMessageIfClaimsPrincipalDoesNotExist">An account could not be found for the provided user ID.</Item>
          </Metadata>
          <IncludeInSso>false</IncludeInSso>
          <InputClaims>
            <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInNames" Required="true" />
          </InputClaims>
          <OutputClaims>
            <OutputClaim ClaimTypeReferenceId="objectId" />
            <OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />
             <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
            <OutputClaim ClaimTypeReferenceId="displayName" />
            <OutputClaim ClaimTypeReferenceId="otherMails" />
            <OutputClaim ClaimTypeReferenceId="signInNames.emailAddress" />

          </OutputClaims>
           <IncludeTechnicalProfile ReferenceId="AAD-Common" />
        </TechnicalProfile>

Rest of the "SelfAsserted-LocalAccount-EmailVerification" is the same as previous post and the claims etc.

<TechnicalProfile Id="SelfAsserted-LocalAccount-EmailVerification">
  <DisplayName>Local Account Email Address Verification</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="ContentDefinitionReferenceId">api.localaccount.emailverification</Item>
    <Item Key="EnforceEmailVerification">true</Item>
  </Metadata>
  <InputClaimsTransformations>
    <InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
  </InputClaimsTransformations>
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="readonlyEmail" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="readonlyEmail" PartnerClaimType="verified.email" Required="true" />
  </OutputClaims>
</TechnicalProfile>

The CreateReadonlyEmailClaim claims transformation is defined as:

<ClaimsTransformation Id="CreateReadonlyEmailClaim" TransformationMethod="FormatStringClaim">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="inputClaim" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="stringFormat" DataType="string" Value="{0}" />
  </InputParameters>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="readonlyEmail" TransformationClaimType="outputClaim" />
  </OutputClaims>
</ClaimsTransformation>

The readonlyEmail claim type is declared as:

<ClaimType Id="readonlyEmail">
  <DisplayName>E-mail Address</DisplayName>
  <DataType>string</DataType>
  <UserInputType>Readonly</UserInputType>
</ClaimType>

What am I missing here?

I also tried this but get a 500 error after login

<TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddressEmailOTP">
    <DisplayName>Reset password using email address</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.localaccountpasswordreset</Item>
    </Metadata>
    <CryptographicKeys>
        <Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
    </CryptographicKeys>
    <IncludeInSso>false</IncludeInSso>
    <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
    </InputClaimsTransformations>
    <InputClaims>
        <InputClaim ClaimTypeReferenceId="readonlyEmail" />
    </InputClaims>
    <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="readonlyEmail" PartnerClaimType="verified.email" Required="true" />
        <OutputClaim ClaimTypeReferenceId="objectId" />
        <OutputClaim ClaimTypeReferenceId="userPrincipalName" />
        <OutputClaim ClaimTypeReferenceId="authenticationSource" />
    </OutputClaims>
    <ValidationTechnicalProfiles>
        <ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddressEmailOTP" />
    </ValidationTechnicalProfiles>
</TechnicalProfile>

Also once email has been verified there is a change email option - we want that disabled or better - removed so that they can't do it after verification and moved to next step

Chris T
  • 155
  • 1
  • 11
  • I know it should be a inputclaim but if I put SelfAsserted-LocalAccount-EmailVerification as in IncludeTechnicalProfile to LocalAccountDiscoveryUsingEmailAddressEmailOTP - gives a 500 error. So not sure how to call that technical profile in there and then I guess we put readonlyEmail as inputprofile ?? – Chris T Mar 01 '19 at 05:00
  • Hi @Chris T. You must include both `` and `` for the LocalAccountDiscoveryUsingEmailAddressEmailOTP technical profile. Can you also copy and paste the `readonlyEmail` claim type declaration in the above question? – Chris Padgett Mar 01 '19 at 22:30
  • @ChrisPadgett I have updated the question with all the xml code. What do I exactly need to do in LocalAccountDiscoveryUsingEmailAddressEmailOTP and what all needs to change in above code?? – Chris T Mar 02 '19 at 06:36
  • @ChrisPadgett tried various combinations but obviously there is a missing link here which I am not seeing... – Chris T Mar 04 '19 at 01:38
  • Hi @Chris T. It might be caused by the `email` claim that's missing. The `AAD-UserReadUsingObjectId` TP returns an output claim of `signInNames.emailAddress`, not `email`, so the `CreateReadonlyEmailClaim` claims transformation should refer to an input claim of `signInNames.emailAddress`, not `email`. – Chris Padgett Mar 04 '19 at 09:33
  • @ChrisPadgett Is it possible to auto-populate email when display control is used for email customization – Parag Jadhav Aug 28 '20 at 12:31

1 Answers1

1

As per @ChrisPadgett comment - The AAD-UserReadUsingObjectId TP returns an output claim of signInNames.emailAddress, not email, so the CreateReadonlyEmailClaim claims transformation should refer to an input claim of signInNames.emailAddress, not email.

Fixed by changing the transformation.

Chris T
  • 155
  • 1
  • 11