Implement a 'Password Reset' with JavaScript and Azure AD B2C

christosmatskas

Christos Matskas

Posted on December 15, 2020

Implement a 'Password Reset' with JavaScript and Azure AD B2C

Azure AD B2C provides a lot of great functionality for dealing with user sign up/sign in and profile management out of the box without the need to write any code. In this blog post I'll show you how to implement "Password Reset" in a (vanilla) JavaScript web app.

Create the Azure AD B2C App Registration

First, we'll register and configure an Azure AD B2C app registration so that we can authenticate and manage users in our JavaScript application.

Open the App Registrations blade in Azure AD B2C and create a new app registration

Alt Text

Provide a meaningful name and leave everything else default before pressing the Register button

Alt Text

Now we can add the Authentication settings we need for our application:

Alt Text

And since we're working with a simple JS application, we need to choose Single Page Application

Alt Text

On the next tab we only need to add a Redirect URI. We don't need to worry about Implicit Flow anymore since MSAL.js v2.x supports PKCE out of the box :), in effect, making our JavaScript applications more secure!

Alt Text

Configure the User Flows

User flows in B2C dictate how users interact with our application. They define experiences such as Sign In/Sign Up, Edit profile etc etc. For this blog post we need a combined SignIn/SignUp and an Password Reset policy.

The first is absolutely mandatory, the other ones are optional to implement but highly recommended if you want a smooth user experience. Let's get to it.

Back at the root of the B2C blade, open the User Flows blade.

Alt Text

First, we'll create our Sign In/Sign Up policy. Press the New User Flow button and select Sign up and sign in and Version -> Recommended

Alt Text

Next we need to provide some details, starting with the name of the policy (has to be unique in our tenant), configure Local Accounts to use email signup and finally the attributes we want to collect and return in our token claims.

Alt Text

Alt Text

Press OK for the user attributes and Create in the user flow.

This concludes the configuration of the Sign In/Sign Up flow.

Bonus tip: You can easily test a User Flow directly from the AAD B2C portal by adding jwt.ms as a Redirect URI to any app registration

Alt Text

The last step in the AD B2C portal is to configure the Password Reset flow.

Alt Text

Alt Text

This concludes all the changes we need to do on the Azure AD B2C portal to accommodate users that need to sign in and reset their credentials.

Writing the code

My code is loosely based on this AAD B2C JS sample but significantly simplified to have bare minimum for the purpose of this blog post

The main MSAL.js code is in the authPopup.js. The rest of the code deals with config settings (authConfig.js) or UI changes in response to user actions (ui.js)



const myMSALObj = new msal.PublicClientApplication(msalConfig);

let accountId = "";
let username = "";

function selectAccount () {
    const currentAccounts = myMSALObj.getAllAccounts();

    if (currentAccounts.length === 0) {
        return;
    } else if (currentAccounts.length > 1) {
        // Add your account choosing logic here
        console.log("Multiple accounts detected.");
    } else if (currentAccounts.length === 1) {
        accountId = currentAccounts[0].homeAccountId;
        username = currentAccounts[0].username;
        welcomeUser(username);
    }
}

selectAccount();

function handleResponse(response) {
    if (response !== null) {
        accountId = response.account.homeAccountId;
        username = response.account.username;
        welcomeUser(username);
    } else {
        selectAccount();
    }
}

function signIn() {
    myMSALObj.loginPopup(loginRequest)
        .then(handleResponse)
        .catch(error => {
            console.log(error);
            if (error.errorMessage) {
                if (error.errorMessage.indexOf("AADB2C90118") > -1) {
                    myMSALObj.loginPopup(b2cPolicies.authorities.forgotPassword)
                        .then(response => handlePolicyChange(response));
                }
            }
        });
}

function signOut() {
    const logoutRequest = {
        account: myMSALObj.getAccountByHomeId(accountId)
    };

    myMSALObj.logout(logoutRequest).then(goodbyUser);
}

function editProfile() {
    myMSALObj.loginPopup(b2cPolicies.authorities.editProfile)
      .then(response => handlePolicyChange(response));
}

function handlePolicyChange(response) {
    if (response.idTokenClaims['acr'] === b2cPolicies.names.editProfile) {
        window.alert("Profile has been updated successfully. \nPlease sign-in again.");
        myMSALObj.logout();
    } else if (response.idTokenClaims['acr'] === b2cPolicies.names.forgotPassword) {
        window.alert("Password has been reset successfully. \nPlease sign-in with your new password.");
        myMSALObj.logout();
    }
}


Enter fullscreen mode Exit fullscreen mode

As you can see, there's not much code to implement to wire up authentication in our JavaScript app using Azure AD B2C.

Password Reset with AAD B2C

The MSAL.js library has a specific way for dealing with password resets. Password resets manifest as exceptions in the login/signin process. When users are presented with the sign in popup/redirect, they have the option to execute a password reset. The password reset throws an exception that developers need to catch and and handle accordingly. The code below shows how the password reset event is captured in code where the users are redirected to the Reset Password flow:



function signIn() {
    myMSALObj.loginPopup(loginRequest)
        .then(handleResponse)
        .catch(error => {
            console.log(error);
            if (error.errorMessage) {
                if (error.errorMessage.indexOf("AADB2C90118") > -1) {
                    myMSALObj.loginPopup(b2cPolicies.authorities.forgotPassword)
                        .then(response => handlePolicyChange(response));
                }
            }
        });
}


Enter fullscreen mode Exit fullscreen mode

If you want to know more about AAD code, check out the documentation here.

Alt Text

Source code.

If you want to see the solution working end-to-end, clone this GitHub repo run it locally.

Summary

As you can see, implementing the password reset functionality with B2C requires 2 steps:

  • Step 1: Configure the appropriate user flow in the B2C portal
  • Step 2: Extend the SignIn method in your code to capture the AAD error thrown due to the user initiating the Password Reset and calling the appropriate user flow

I hope this is helpful but as always, feel free to let us know if you have any other questions or want to us to blog or stream something that you find challenging.

💖 💪 🙅 🚩
christosmatskas
Christos Matskas

Posted on December 15, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related