Hello i am trying to write an azure b2c custom policy that split email validation sending a custom email with sendgrid(Display Control) and after that ask the user to input values like name or surname.
I am using the following technical profile to get the email and validate it with a custom mail using sendgrid and displays controls:
<TechnicalProfile Id="EmailVerification">
<DisplayName>Initiate Email Address Verification For Local Account</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.localaccountsignup</Item>
<Item Key="language.button_continue">Continue</Item>
<!--OTP validation error messages-->
<Item Key="UserMessageIfSessionDoesNotExist">You have exceed the maximum time allowed.</Item>
<Item Key="UserMessageIfMaxRetryAttempted">You have exceed the number of retries allowed.</Item>
<Item Key="UserMessageIfInvalidCode">You have entered the wrong code.</Item>
<Item Key="UserMessageIfSessionConflict">Cannot verify the code, please try again later.</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<DisplayClaims>
<DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
</DisplayClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
</OutputClaims>
</TechnicalProfile>
The display control code is the following:
<DisplayControls>
<DisplayControl Id="emailVerificationControl" UserInterfaceControlType="VerificationControl">
<DisplayClaims>
<DisplayClaim ClaimTypeReferenceId="email" Required="true" />
<DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" Required="true" />
</DisplayClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" />
</OutputClaims>
<Actions>
<Action Id="SendCode">
<ValidationClaimsExchange>
<ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="GenerateOtp" />
<ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="SendGrid" />
</ValidationClaimsExchange>
</Action>
<Action Id="VerifyCode">
<ValidationClaimsExchange>
<ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="VerifyOtp" />
</ValidationClaimsExchange>
</Action>
</Actions>
</DisplayControl>
</DisplayControls>
The next step is to ask the user for some additional input with the following technical profile:
<TechnicalProfile Id="LocalSignUpWithREmailWithToS">
<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">Create</Item>
<!-- Sample: Remove sign-up email verification -->
<Item Key="EnforceEmailVerification">False</Item>
</Metadata>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CreateReadonlyEmailClaim" />
</InputClaimsTransformations>
<InputClaims>
<!--Sample: Set input the ReadOnlyEmail claim type to prefilled the email address-->
<InputClaim ClaimTypeReferenceId="readOnlyEmail" />
</InputClaims>
<DisplayClaims>
<DisplayClaim ClaimTypeReferenceId="newPassword" Required="true" />
<DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
<DisplayClaim ClaimTypeReferenceId="displayName" Required="true" />
<DisplayClaim ClaimTypeReferenceId="givenName" Required="true" />
<DisplayClaim ClaimTypeReferenceId="surName" Required="true" />
</DisplayClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
<!-- Sample: Display the ReadOnlyEmail claim type (instead of email claim type)-->
<OutputClaim ClaimTypeReferenceId="readOnlyEmail" Required="true" />
<OutputClaim ClaimTypeReferenceId="newPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
<OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
<OutputClaim ClaimTypeReferenceId="newUser" />
<!-- Optional claims, to be collected from the user -->
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="givenName" />
<OutputClaim ClaimTypeReferenceId="surName" />
<OutputClaim ClaimTypeReferenceId="AgreedToTermsOfService" Required="true" />
<!--Sample: This is set to "false" by default to bypass OrchestrationStep 5 during Sign-in-->
<OutputClaim ClaimTypeReferenceId="renewalTOSrequired" DefaultValue="false" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserWriteUsingLogonEmail" />
</ValidationTechnicalProfiles>
<!-- Sample: Disable session management for sign-up page -->
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
But it appears that the outputClaim "EMAIL" from the first step is failing when executing the claims transformation
<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>
I was able to capture the error with application insights
Exception Message:A Claim of ClaimType with id "email" was not found, which is required by the ClaimsTransformationImpl of Type "Microsoft.Cpim.Data.Transformations.FormatStringClaimTransformation" for TransformationMethod "FormatStringClaim" referenced by the ClaimsTransformation with id "CreateReadonlyEmailClaim" in policy "B2C_1A_TrustFrameworkExtensionsReMeSplit" of tenant "XXXXXXX.onmicrosoft.com"., Exception Type:PolicyException, CorrelationID.
Does anyone know what is the correct form to read the output claim "EMAIL" from the display control to use it inside the claim transformation?