Rory Braybrook
Jun 3 · 3 min read

I recently gave a presentation on Azure AD B2C custom policies.

The collateral for the demo. is on Github pages.

As part of this, I was looking for a killer demo. to demonstrate a B2C SignInSignUp user journey calling a REST API from custom policies during a sign-up flow.

In Azure AD, if you pick a new password that is suspect because it appears in so many breaches (e.g. “Password123”), you get a message saying:

“We’ve seen this password too many times. Please pick a more secure one”

This feature is not yet on B2C and I realised that I could implement this using “Pwned Passwords”.

This is described in much more detail here.

This is invoked by the API:{hashPrefix}

Essentially, you hash the password using SHA1 and then use the first five digits as the hash prefix.


This is just a part of it but essentially each line is the rest of the hash (i.e. minus the first five characters) and the number of times each hash has appeared in a breach.

We could use this by having B2C call an Azure webAPI (a REST API) and the REST API could then call

The TrustFrameworkExtensions.xml custom policy (in the collateral above) looks like:

<Item Key=”ServiceUrl”></Item>

<Item Key=”AuthenticationType”>None</Item>

<Item Key=”SendClaimsIn”>QueryString</Item>

The “ServiceURL” contains the URL of the web API.

There is no authentication so “AuthenticationType” is “None”.

It’s a GET request so we send the claims in the “QueryString”.

We map “NewPassword” to “password” so the API call looks like:


The user journey calls “LocalAccountSignUpWithLogonEmail”

We extend this technical profile by adding a validation technical profile that calls the “REST-API-PwnedPassword” technical profile and this calls the Azure web API.

The Azure webAPI code (in the collateral above) is:

So we hash the password, send off the first five characters to the API, get the response and then search for the rest of the hash. Once we get the correct line, we get the number of times that password has appeared in a breach.

If it has appeared, we send an error message back to B2C with a “ HttpStatusCode.Conflict” code that tells B2C to display the error and stop the user journey.

The technical profile “LocalAccountSignUpWithLogonEmail” has two claims added to it.

<! — Optional claims, to be collected from the user →
<OutputClaim ClaimTypeReferenceId=”extension_ugName” />
<OutputClaim ClaimTypeReferenceId=”extension_ugVenue” />

As this is a self-asserted technical profile (i.e. the user is expected to provide some input), these fields will appear on the sign-up form.

Let’s see what happens when we run the sign-up journey.

We’ve added some branding so we see:

We click “Sign up now”:

Notice the two new textboxes containing the user group information “ugName” and “ugVenue”.

We use password “Password123”.

And we get the “Pwned Password” error!

If we enter a password that has not appeared in a breach, we get the JWT back with the user group fields.

All good!

The new control plane

“Identity is the new control plane”. Articles around Microsoft Identity, Auth0 and identityserver. Click the “Archive” link at the bottom for more posts.

Rory Braybrook

Written by

NZ Microsoft Identity dude. Microsoft MVP. Azure AD/B2C/ADFS. Plus Auth0/identityserver. N. Shore .NET UG Admin. Presentations:

The new control plane

“Identity is the new control plane”. Articles around Microsoft Identity, Auth0 and identityserver. Click the “Archive” link at the bottom for more posts.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade