Upskilling on Azure B2C custom policies — Inheritance

tutorial by Twin rizki from the Noun Project

I have organised the series as a list inside Medium so you can see the rest of the series.

Take a look at the MFA starter pack.

Notice how the SignUpOrSignin policy inherits from the extension policy:


and the extension policy inherits from the base policy:


My recommendation is never to change the base and extension files.

If you need to add code, create a new extension file and link it in e.g.

SignUpOrSignin →your new extension →extension →base

Add your code to the new extension file.

If you do this, it is easy to merge in any new policy fixes and updates that may be added to the starter pack files. It also means that code for a particular use case is only added in that new extension file rather than the base file being continually added to and getting bigger and bigger.

So let’s start.

At this point, I assume you’ve uploaded the base and extensions file and the SignupOrSignin one.

Now your customer wants the RelyingParty (in SignupOrSignin) to have one extra claim i.e. accountEnabled.

So add it:

<OutputClaim ClaimTypeReferenceId="email" />
<OutputClaim ClaimTypeReferenceId="accountEnabled" />
<OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub"/>

Now upload it.

You get the error:

Claim type "accountEnabled" is the output claim of the relying party's  technical profile, but it is not an output claim in any of the steps of  user journey "SignUpOrSignIn".

So now we need to understand what is going on.

When you start looking at a custom policy, always start with the user journey.

The user journey is:

<DefaultUserJourney ReferenceId="SignUpOrSignIn" />

Find this in the base policy.

It has the following steps:

  • SelfAsserted-LocalAccountSignin-Email
  • LocalAccountSignUpWithLogonEmail
  • AAD-UserReadUsingAlternativeSecurityId-NoError
  • SelfAsserted-Social
  • AAD-UserReadUsingObjectId
  • AAD-UserWriteUsingAlternativeSecurityId
  • PhoneFactor-InputOrVerify
  • AAD-UserWritePhoneNumberUsingObjectId
  • JwtIssuer

The AlternativeSecurityId is for social. You will note that the starter pack includes the ability to login with Facebook.

PhoneFactor is for MFA.

We will sign-in not sign-up.

So it looks like the error is in AAD-UserReadUsingObjectId. We are not reading the attribute. Have a look in the base files and you will see that is indeed the case. So we have to add it.

Intuitively, we just add this attribute to the base file method. Do not do this.

Exercise 1

Create a new custom policy file and add it between the SignupOrSignin one and the TrustFrameworkExtensions one. Let’s call it ExerciseExtensions.xml.

So SignupOrSignin → ExerciseExtensions →TrustFrameworkExtensions

Add a new TechnicalPolicy (TP) in the ExerciseExtensions policy and call it “AAD-UserReadUsingObjectId” i.e. the same name as in the base file.

Add accountEnabled to this. It will be the only output claim.

When B2C sees this, it merges the two TP effectively adding the output claim but leaving the base file untouched.

Because it’s always a merge operation, copying and removing things will never work. Copying and adding will work.

If you are stuck, look here.

Create a user through the portal.

Now run the policy and sign-in as that user.

The policy will then ask you to proof-up i.e. add MFA.

All good!



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rory Braybrook

Rory Braybrook


NZ Microsoft Identity dude and MVP. Azure AD/B2C/ADFS/Auth0/identityserver. StackOverflow: Presentations: