0

I have a password reset flow. I'm sending custom email templates using sendgrid. Now I want to change the verification code with a "verification link".

I found a sample for signup invitation that is similar but not really a sample for password reset.

Does somebody already tried this?

Thanks

LockTar
  • 5,364
  • 3
  • 46
  • 72

1 Answers1

0

If you understood the flow in the signup invitation, you could use the same logic to implement a password reset flow.

  • Instead of sending a link to the signup invitation flow, send an email with a link to your custom password reset flow.
  • In the user journey, After extracting the email from Id token hint, use a technical profile to read user details.
  • You can always add an extra layer of security by asking the user to do a multi-factor authentication using phone or email.
  • After that it's the same steps from the password reset policy to display the password collection page and save the updated password.

The user journey would roughly look something like this

<UserJourney Id="PasswordReset">
    <OrchestrationSteps>

        <!-- Track that we have received an authentication request -->
        <OrchestrationStep Order="1" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackAuthenticationRequest" TechnicalProfileReferenceId="AzureInsights-AuthenticationRequest" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="2" Type="GetClaims" CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims" />

        <OrchestrationStep Order="3" Type="ClaimsExchange">
            <Preconditions>
                <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
                    <Value>email</Value>
                    <Action>SkipThisOrchestrationStep</Action>
                </Precondition>
            </Preconditions>
            <ClaimsExchanges>
                <ClaimsExchange Id="SelfAsserted-Unsolicited" TechnicalProfileReferenceId="SelfAsserted-Unsolicited"/>
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="4" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="UserReadUsingEmailAddressExchange" TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Track that the authentication step is completed -->
        <OrchestrationStep Order="5" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackAuthenticationComplete" TechnicalProfileReferenceId="AzureInsights-AuthenticationComplete" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Optional MFA steps 6 to 8. Replace with email mfa if needed -->
        <!-- Track that the mutifactor authentication step is initiated -->
        <OrchestrationStep Order="6" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackMultifactorInitiate" TechnicalProfileReferenceId="AzureInsights-MultifactorInitiate" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="7" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Track that the mutifactor authentication step is completed -->
        <OrchestrationStep Order="8" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackMultifactorComplete" TechnicalProfileReferenceId="AzureInsights-MultifactorComplete" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Track that the password reset flow is started-->
        <OrchestrationStep Order="9" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackPasswordResetInitiate" TechnicalProfileReferenceId="AzureInsights-PasswordResetInitiate" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="10" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordUsingObjectId" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <!-- Track that the password reset flow is completed-->
        <OrchestrationStep Order="11" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackPasswordResetComplete" TechnicalProfileReferenceId="AzureInsights-PasswordResetComplete" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="12" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
            </ClaimsExchanges>
        </OrchestrationStep>

        <OrchestrationStep Order="13" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

        <!-- Track that we have successfully sent a token -->
        <OrchestrationStep Order="14" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="TrackTokenIssued" TechnicalProfileReferenceId="AzureInsights-TokenIssued" />
            </ClaimsExchanges>
        </OrchestrationStep>

    </OrchestrationSteps>
    <ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
  • In the BuildUrl Method from HomeController in API, change the policy id from app settings with your custom password reset policy id
private string BuildUrl(string token)
{
    string nonce = Guid.NewGuid().ToString("n");

    return string.Format(this.AppSettings.B2CSignUpUrl,
            this.AppSettings.B2CTenant,
            this.AppSettings.B2CPasswordResetPolicy,
            this.AppSettings.B2CClientId,
            Uri.EscapeDataString(this.AppSettings.B2CRedirectUri),
            nonce) + "&id_token_hint=" + token;
}

Note: The BuildUrl method may have to be modified once you are using custom domains in production

sabique
  • 223
  • 1
  • 7