I’m working on an Azure AD B2C custom policy to validate an email through a RESTful endpoint. If the validation and email verification are successful, I want to generate a token. I’m currently at the last step to generate the token, but I get the following URL: https://jwt.ms/?code=eyJraWQiOiI2WllIUmttREwyXzBvREF6UHhQWHZ. without any token in there. I am using it’s went to the last step.
My requirements:
Use only email for validation and token generation.
Validate the email through a RESTful endpoint.
Generate the token if the validation and verification are successful.
Here are my questions:
- What am I missing? The process reaches the last step, but the token is not generated. What did I do wrong?
- Between steps 5 and 7, I’m repeating the same process to give the user three attempts to validate the email. Is there a better way to achieve this?
Relying Party
<TechnicalProfile Id="JwtIssuerWithEmail">
<DisplayName>JWT Issuer With Email</DisplayName>
<Protocol Name="None" />
<OutputTokenFormat>JWT</OutputTokenFormat>
<Metadata>
<Item Key="client_id">{service:te}</Item>
<Item Key="SendTokenResponseBodyWithJsonNumbers">true</Item>
<Item Key="issuer_refresh_token_user_identity_claim_type">email</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
<Key Id="issuer_refresh_token_key" StorageReferenceId="B2C_1A_TokenEncryptionKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="tenantId" PartnerClaimType="tid" />
</OutputClaims>
</TechnicalProfile>
User Journey
<UserJourney Id="SignInAndSignUpWithEmailVerification">
<OrchestrationSteps>
<!-- Register application insight -->
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="TrackSignInRequest" TechnicalProfileReferenceId="AzureInsights-SignInRequest" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Show email registration page -->
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedEmailRegistration" TechnicalProfileReferenceId="SelfAsserted-EmailRegistration-Custom" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Check if the email is valid -->
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="REST-CheckEmailValidity" TechnicalProfileReferenceId="REST-CheckEmailValidity" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Second try -->
<OrchestrationStep Order="4" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>isEmailValid</Value>
<Value>true</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedEmailInvalidRetry2" TechnicalProfileReferenceId="SelfAsserted-EmailRegistration-Custom-Retry" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Third try -->
<OrchestrationStep Order="5" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>isEmailValid</Value>
<Value>true</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedEmailInvalidRetry3" TechnicalProfileReferenceId="SelfAsserted-EmailRegistration-Custom-Retry" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- After third try it fails -->
<OrchestrationStep Order="6" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>isEmailValid</Value>
<Value>true</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SelfAssertedEmailInvalidFailed" TechnicalProfileReferenceId="SelfAsserted-EmailRegistration-Custom-Failed" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Transform email to readOnlyEmail -->
<OrchestrationStep Order="7" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="TransformEmailToReadOnlyEmail" TechnicalProfileReferenceId="TransformEmailToReadOnlyEmail" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Show custom email verification page -->
<OrchestrationStep Order="8" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="UserProfile_EmailVerification_Custom" TechnicalProfileReferenceId="EmailVerification-Custom-UI" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Generate the token -->
<OrchestrationStep Order="9" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuerWithEmail" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>