Creating Custom policies in Azure Active Directory B2C — easy, uh?
In 8 simple steps. Ready, let’s go!

Photo by Taylor Binkley on Unsplash

Why Custom policies?

In Azure Active Directory B2C, custom policies are used to address complex or custom scenarios. For example, if your organisation’s password policy require a combination of 3 numbers, 2 capital letters and 5 symbols, and must be at minimum 888 characters long. Just saying. Some custom scenario that the regular built-in User flow does not cater for out-of-the-box. In this article, I will describe an example of configuring a password change using custom policies. In a typical password change flow, it will request the user for a unique email address. However, there are valid situations where users log in using a unique username. They do not have an email address to supply, and hence the out-of-the-box change password policy with email verification step will not work. This is where custom policies come in. 8 simple steps!

Step 1 Create your signing and encryption keys

From your B2C tenant, navigate to Azure AD B2C, and select Identity Experience Framework to create your signing key and encryption key.

Go to Policy keys, and click Add.

Under Azure AD B2C, from Identity Experience Framework, Add Policy keys

For options, select Generate. For Key type, select RSA. For Key usage, select Signature. Then, Create. I have named my signing key TokenSigningKeyContainer. See picture below. This will create your signing key.

Signing key

To create your encryption key, repeat the add policy key step again, and this time, for Key usage, select Encryption. I have named my encryption key TokenEncryptionKeyContainer.

Encryption key

All sweet for step 1. Proceed to step 2!

Step 2 Register the IdentifyExperienceFramework and ProxyIdentityExperienceFramework app

Azure AD B2C requires you to register two applications that it uses to sign up and sign in users with local accounts:

IdentityExperienceFramework — a web API, and ProxyIdentityExperienceFramework — a native app with delegated permission to the first app (IdentityExperienceFramework).

Still from within the B2C tenant, navigate to the Azure Active Directory blade, and then go to App registrations. Note that this is the Azure Active Directory, App registrations. Then, select New registration to register your app.

In Azure Active Directory, register the 2 apps — IdentityExperienceFramework and ProxyIdentityExperienceFramework

Name = IdentityExperienceFramework . you can call it whatever you like but make the names meaningful for readability. Select Accounts in this organizational directory only.

Supported account types — Accounts in this organizational directory only

For Redirect URI, select Web, and then enter https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com where your-tenant-name is your Azure AD B2C tenant domain name.

Check the box for “Grant admin consent to openid and offline_access permissions”.

Check the checkbox to grant admin consent

Select Register. Record the Application (client) ID for use for later.

Next, for the app IdentityExperienceFramework that you had just created, expose an API by adding a scope.

Add a scope

Create a scope that allows custom policy execution in your Azure AD B2C tenant

Select Add scope.

Next, register your second app ProxyIdentityExperienceFramework. Still from the Azure Active Directory blade, go to App registrations. Click on New registration.

Name = ProxyIdentityExperienceFramework. Same as before, select Accounts in this organizational directory only. However, for Redirect URI, you select “Public client/native (mobile & desktop)” and in the textbox, enter in: myapp://auth

Redirect URI

Check the box for “Grant admin consent to openid and offline_access permissions”. Select Register. Record the Application (client) ID for use for later.

Specify that this app is a public client. Go to Authentication, and under Advanced settings, toggle the button to Yes.

Allow public client flows

Next, configure the second app to have delegated permissions to your first app. Navigate to “API permissions”, then select Add a permission. Under My APIs, select the IdentityExperienceFramework application.

Select the IdentityExperienceFramework to see its exposed permissions to delegate

Select the user_impersonation scope.

check the checkbox for user_impersonation

Add permissions. You should see the API/permissions name added. Then, click on the button that doesn’t look like a button “Grant admin consent for your-tenant-name”. (Believe me, this intriguing UI ‘feature’ has tripped up many people!)

click on this button “Grant admin consent for …”

Ensure you are signed in with the right IAM permissions to grant this admin consent. Select Accept and then verify that “Granted for…” appears.

And you are done for Step 2. Remember to store the values of the Application (client) ID of:

IdentityExperienceFramework — we will call this App ID 1, and ProxyIdentityExperienceFramework — we will call this App ID 2

These are very very long strings of numbers and alphabets. We will use them in Step 5 later on.

Step 3 Register your app

This is a good old usual app registration step, nothing fancy. Still from within the B2C tenant, App registrations, select New registration. My example app is called webapp1. For supported account types, select the “Accounts in any identity provider”

For Redirect URI, select Web, and then enter https://jwt.ms so that you visibly test later on.

Select Register. Done! Nice and easy.

Step 4 Configure your custom policies (XML files) — find and replace “yourtenant”

Now, the golden moment that you have been waiting for — to actually configure your custom policies! The policies are a family of XML files that work together to express your policies.

The ‘grandfather’ of all is the Base file (TrustFrameworkBase.xml) which typically do not require any modification. Then, next down the inheritance hierarchy is the Extension file (TrustFrameworkExtensions.xml) which is where you will make majority of the configuration changes in order for your B2C tenant to function with your new custom policy. And finally, the Relying party files (eg. Password Change XML file) is the XML files where you express those specific tasks.

My experience told me that if you find a bug, it is often in the TrustFrameworkExtensions.xml file. For some weird reason, the bug will not manifest itself until you upload the Relying party files, which will give you a false root cause of where the bug really came from. So, in summary if you found a bug, likely it will be in the TrustFrameworkExtensions.xml. Likely, but of course all bugs are special, so hunt them down until they are squashed!

Download your starter pack from GitHub if you haven’t already got them. I selected the SocialAndLocalAccounts folder. There are 5 XML files.

The 5 XML files in the SocialAndLocalAccounts

Find and replace carefully — typos often result in excruciating bug-finding hell. In all the XML files, replace the string “yourtenant” with the name of your B2C tenant in small caps. This is your B2C tenant. Not your non-B2C tenant. For example,

TenantId=”yourtenant.onmicrosoft.com”

should be replaced with:

TenantId=”superpamb2ctenant.onmicrosoft.com”

and

PublicPolicyUri=”http://yourtenant.onmicrosoft.com/B2C_1A_TrustFrameworkBase">

should be replaced with:

PublicPolicyUri=”http://superpamb2ctenant.onmicrosoft.com/B2C_1A_TrustFrameworkBase">

Find and replace “yourtenant” in all the XML files. Make sure there are no more “yourtenant” words floating around.

Step 5 Edit the TrustFrameworkExtensions to call the Relying party activity eg. Password Change

For the TrustFrameworkExtensions file, again tread carefully here. Simple typos can result in bug-finding hell. Go slow, in order to go fast!

Edit the TrustFrameworkExtensions to call the Password Change XML (PasswordChange.xml) which you will create in Step 6.

First, configure your ClaimsSchema inside of your BuildingBlocks so that it will ask the user for the old password first.

Configure ClaimType for oldPassword

I did not make any change to the Facebook ClaimsProvider. This has got nothing to do with the Password Change, but I left the code there unchanged anyway.

Next, under the ClaimsProvider for “Local Account SignIn”, my configuration as below. Remember those Application (client) ID from Step 2? Ensure that you have the right IDs of App ID 1 and App ID 2 in the right places here. (beware don’t be confused in putting them in the wrong places). They are both very long strings of numbers and alphabets.

Also, replace the B2C tenant name with your own.

ClaimsProvider for “Local Account SignIn”

And then ClaimsProvider for “Local Account Password Change”, my configuration as below.

ClaimsProvider for “Local Account Password Change”

Check that all tags close nicely.

Add a User Journey for PasswordChange.

UserJourney for PasswordChange

Step 6 Develop your Password Change XML

Create a new file by copying and pasting from signup_signin.xml and re-name the new file “PasswordChange.xml”. Place it in the same directory as the rest of the 5 XML files.

Modify only the RelyingParty section to have these configs below. The rest of the file is unchanged from what we copied from the signup_signin.xml.

RelyingParty for PasswordChange

Check that all tags still close nicely.

Step 7 Sequence does matter!

Next we will upload all the 6 XML files into your Azure AD B2C tenant, and the sequence of upload does matter.

From the B2C tenant, under Azure AD B2C, select the Identity Experience Framework. Click on Upload custom policy.

Upload your custom policies in sequence

Upload the 6 XML files in this sequence, starting with TrustFrameworkBase.xml as the first one to be uploaded:

TrustFrameworkBase.xml TrustFrameworkExtensions.xml Signup_signin.xml ProfileEdit.xml PasswordReset.xml PasswordChange.xml

As you upload the files, Azure adds the prefix B2C_1A_ to each of them.

They should all be uploaded successfully and cross fingers that they will be bug-free! At this stage, you could potentially find bugs if there was some typo at previous steps. Especially Step 5.

Step 8 Test your policy

Once they are all uploaded successfully, it will be time to test Password Change! Under Custom policies, select B2C_1A_PasswordChange.

Under select application, select webapp1 which you had created in Step 3. Select reply URL is: https://jwt.ms

Test your Custom policy

Then, Run now!

If all goes well, you will see the Sign in name (username) and password.

Custom policy for Sign In

And from there, you will be able to change password using your brand new Change Password custom policy.

Custom policy for Change Password

When you see the blue jwt.ms screen, it’s a success!

the familiar blue jwt.ms screen

Happy dance, Let’s celebrate!!!
['Pamela Tung']
['Custom Policies', 'Change Password', 'Azure B2c', 'Azure Active Directory', 'Azure']