The image shows a door representing access to an application.
Photo by Dima Pechurin on Unsplash

Combining Sign Up and Sign In Into a Single Policy Using Azure AD B2C

Michael Collins
Neudesic Innovation
5 min readJan 30, 2022

--

In the previous two posts, I built a working sign up relying party policy that allowed new users to sign up and create a local user account using a username and password. I next created a relying party policy that allowed users to log in and be authenticated by Azure Active Directory B2C using their username and password. What happens if a new user accidentally goes to the login screen or if the application does not have a choice to give the user the option of navigating to the sign up screen? With Azure Active Directory B2C, it is fairly easy to create a combined sign up or sign in relying party policy.

This is the seventh post in a series on Azure Active Directory B2C and how to use Azure Active Directory B2C to create an identity management system for a Software-as-a-Service application. If you are new to this series, I recommend reading the earlier posts in the series:

  1. Building Application Identity Solutions using Azure AD B2C
  2. Configure Azure AD B2C For Customization
  3. Understanding the B2C Directory
  4. Sign Up or Sign In Users With Azure AD B2C: Part 1
  5. Sign Up New Users Using Azure AD B2C
  6. Log In With Local Accounts on Azure AD B2C

Refactoring the Existing Custom Policies

In my last post, I introduced the concept of custom policy inheritance and created a base policy by extracting some of the definitions that were common between the sign up and log in stories. Now that we’re going to combine sign up and log in into a single policy, we can pretty much move everything that we have defined so far into the base policy. I moved all of the <BuildingBlocks> definitions from signup.xml and login.xml and then moved them into base.xml. I also moved all of the <ClaimProvider>definitions out of signup.xml and moved them into base.xml because our new custom policy will reuse all of them. I moved all of the <ClaimProvider> elements except for the ShowLogInForm technical profile in login.xml and moved them to base.xml to be shared by the new custom policy. The updated base.xml file looks like this:

Creating the Relying Party Policy

I started the new policy by creating the relying party policy definition. The relying party policy looks similar to the login policy from the last post. It accepts the signInName claim as an input to allow the client application to populate the username field in the login form.

Defining the User Journey

The first place where we see a significant difference now is in the user journey for the relying party policy. The LogInOrSignUp user journey is a little more complex than our earlier user journeys and has three orchestration steps.

The first orchestration step mirrors the first step in the previous Login user journey. The orchestration step presents the login form to the user to enter their username or password using the ShowLogInOrSignUpForm self-asserted technical profile. The ShowLogInOrSignUpForm technical profile differs from the ShowLogInForm technical profile that we created in the previous article because it uses the api.signuporsignin content definition:

Notice in the <DataUri> element that the api.signuporsignin content definition uses the unifiedssp page identifier. The unifiedssp page identifier tells Azure Active Directory B2C that the content definition presents a form for logging in using a local account. The unifiedssp page identifier will also render the sign up link.

In the ShowLogInOrSignUpForm technical profile, we specify a value for the SignUpTarget metadata key. When a self-asserted technical profile presents a unifiedssp page, the technical profile will use the SignUpTarget metadata value to identify which <ClaimsExchange> element to execute to perform the user sign up in the orchestration step following the current orchestration step.

In the ShowLogInOrSignUpForm technical profile, I also set the setting.forgotPasswordLinkLocation metadata value to None. Because I have not implemented a password recovery flow yet, there’s no point in showing the link for a forgotten password, so I am disabling it for now.

In the second orchestration step, we introduce our first precondition. The precondition looks at the objectId claim to determine if the claim exists. If objectId exists, it exists because the user was authenticated by filling in the log in form in the first orchestration step. If the user clicked on the sign up link in the form, then the first orchestration step ended and the user is advanced to the second orchestration step to execute the <ClaimsExchange> element with the identifier SignUpUser. If the objectId claim exists, then the second orchestration step will be skipped.

The SignUpUser claims exchange uses the ShowSignUpForm technical profile to present the sign up form and Crete the user account. This is the same technical profile that we created for the sign up user story earlier in this series.

If the user either signs up or signs in, then the third orchestration step will be executed and the JWTIssuer technical profile will be executed to generate the JSON Web Token containing the user’s identifier information.

Testing the Combined Policy

With the new combined sign up or log in policy created, it is time to test. Because I made changes to the base policy, the previous sign up policy, and the log in policy, I deleted them all and re-imported them into my Azure Active Directory B2C tenant. When I run the new custom policy, I get the login screen with a link to sign up:

Log in form with the link to sign up

If I click the sign up link, I am next taken to the sign up form where I can enter my preferred username and enter the password twice:

Sign up form

If I log in or sign up, I am then taken to https://jwt.ms where I can view the identity token that was issued by Azure Active Directory B2C.

Where Have We Gone?

We have gone from having separate sign up and login policies to now having a policy that will allow users to log in if they have an existing account, or sign up for a new local directory account. This will play into the next post where I will show how to use Azure Active Directory B2C to authenticate users for an application.

Updated Listings

--

--

Michael Collins
Neudesic Innovation

Senior Director of Application Innovation at Neudesic; Software developer; confused father