Rory Braybrook
May 15 · 6 min read

I’ve been doing a lot of work with custom policies lately and came across a number of things that might help other custom policy developers so I thought it worth while to note them.

This article will be updated as I come across other tips and tricks.

Custom policies

Custom Signin policy

There is a custom SignUpOrSignin policy but no Signin only policy.

You can achieve this by setting SignUp to “False”.

<Item Key=”setting.showSignupLink”>False</Item>

Customise screen UI

These settings turn the feature on / off.

The default is “true” = feature on.

  • setting.showContinueButton
  • setting.showCancelButton
  • EnforceEmailVerification (removes the need to verify the email — useful for testing)
  • Also PartnerClaimType=”Verified.Email” can be deleted

Customise error messages

In the “ContentDefinitions”, you can customise the error message in the “RecoveryUri” section of the flow e.g. “api.signuporsignin”.

<ContentDefinition Id=”api.idpselections”>
<! — <RecoveryUri>~/common/default_page_error.html</RecoveryUri>

However, this does not work if B2C throws an internal exception.

To cover that case, customise this section:

<! — This content definition is to render an error page that displays unhandled errors. →
<ContentDefinition Id=”api.error”>


You can alter the message texts by “localising” English to English! i.e.

<ContentDefinition Id=”api.signuporsigninwithkmsi”>
<Item Key=”DisplayName”>Signin and Signup with KMSI</Item>
<LocalizedResourcesReferences MergeBehavior=”Prepend”>
<LocalizedResourcesReference Language=”en” LocalizedResourcesReferenceId=”api.localaccountsignup.en” />
</LocalizedResourcesReferences >


<Localization Enabled=”true”>
<SupportedLanguages DefaultLanguage=”en” MergeBehavior=”ReplaceAll”>
<LocalizedResources Id=”api.localaccountsignup.en”>
<LocalizedString ElementType=”ClaimsProvider” StringId=”SignUpWithLogonEmailExchange”>Email signup</LocalizedString>
<LocalizedString ElementType=”UxElement” StringId=”forgotpassword_link”>Forgot Password?</LocalizedString>
<LocalizedString ElementType=”UxElement” StringId=”createaccount_link”>Register</LocalizedString>

The list of messages you can change is here. More info. here.


A neat trick is to set the reply_uri to “”.

This enables you to see the JWT sent by the custom policy.

Calling REST API

The B2C mechanism for this only allows the GET and POST method. If you want to use one of the others e.g. PATCH, then use the REST interface to call an Azure web API or Azure function and implement the functionality there.

Extension attributes

The name of the extension attribute changes between accessing it via custom policies and via the GraphAPI.

For the Graph API , the name includes the clientID of the standard b2c-extensions-app. (Defined under “AppRegistrations” in the Azure AD section of the tenant, not the Azure AD B2C section).

“extension_199…770_isActive”: “False”

The name in the custom policy is:


More info. here.

Setting values to attributes

If you want to write a specific value to an attribute e.g. in “AAD-UserWriteProfileUsingObjectId”, use this format.

<PersistedClaim ClaimTypeReferenceId=”some_attribute” DefaultValue=”true” AlwaysUseDefaultValue=”true”/>

This e.g. sets the attribute to “true”.

Password policies

The basics are described here.

However, this is discussed in more detail using “Predicates” here.

Also, note that if you downgrade the policy e.g. from “Strong” to “Simple” (8 characters minimum — no restrictions on characters), you also need to disable the policy in the Relying Party.

<InputClaim ClaimTypeReferenceId=”passwordPolicies” DefaultValue=”DisablePasswordExpiration, DisableStrongPassword”/>

Policy naming

The name of the custom policy displayed in B2C is not derived from the name of the xml file.

It is derived from the “PublicPolicyUri” value in the xml file.


The name displayed will be:



The “User Journey Recorder” is pretty much a must.

More details here.

If you have set up “Application Insights”, an easy way to find the error in Analytics is to use the term:

search “exception”


search “An error occurred while processing the request”


If you want to add another IDP e.g. ADFS, you still need to use the Social templates e.g. “SocialAndLocalAccounts”.

“Social” includes federation.

It will not work with “LocalAccounts”.


B2C will not work with any IDP that has self-signed certificates.

They have to be CA issued ones.

“Let’s Encrypt” is a free option to create the certificate.


If you want your custom policies to use JavaScript for the application branding etc., you must add an element to your custom policy, select a page contract, and use in your requests.

Content definitions

You can create your own content definitions with arbitrary id’s e.g. “api.registration.error” but they need to inherit a DataUri from the list.


The error message is something like:

“User journey ‘SignIn’ in policy ‘B2C_1A_Policy’ of tenant ‘’ has 2 sendClaims steps. Please specify a DefaultCpimIssuerTechnicalProfileReferenceId attribute set to the default issuer technical profile reference id”

To get around this, add this to your UserJourney start tag:


e.g. the User Journey would look like:

<UserJourney Id=”SignUpSignIn” DefaultCpimIssuerTechnicalProfileReferenceId=”JwtIssuer”>

Thanks to the Advisors for this tip!


There is a collection of utilities here.

Custom policy manager

This API allows you to upload and manage custom policies programmatically.

Note: This API only accepts user tokens, and not application tokens.

This sample is a Windows Forms interface that allows you to invoke various functions.

  • Select Only show RPs to only show the Relying Party files in the Polices list. You must List Policies for this to update the list based on the selection.
  • Select a Policy and click Delete Policy to delete the policy from the tenant.
  • Select Delete all policies to delete all policies in this tenant.
  • Select Get Access token if you would like to also acquire an access token. This will only work if B2C Resource is not null. Enter the scopes into the B2C Resource text field.
  • To launch a policy, select the Relying Party file from the policy list, and then click Launch with IE or Launch with Chrome. Both options will open an private window.
  • To test a SAML Relying Party, click the SAML SP button. This will use a test site ( to build a SAML request for your B2C Policy to the authentication endpoint. The b2csamlrp will also parse the resulting SAML Assertion from B2C.

This use the TrustFrameworkPolicy resource type.

Graph API

Write-up here.

GitHub repository here.

This sample is a Windows command-line interface (CLI) that allows you to invoke various methods.

B2C Help gives:

Get-User : Read users from your B2C directory. Optionally accepts an ObjectId as a 2nd argument, and query expression as a 3rd argument.
Create-User : Create a new user in your B2C directory. Requires a path to a .json file which contains required and optional information as a 2nd argument.
Update-User : Update an existing user in your B2C directory. Requires an objectId as a 2nd arguemnt & a path to a .json file as a 3rd argument.
Delete-User : Delete an existing user in your B2C directory. Requires an objectId as a 2nd argument.
Get-Extension-Attribute : Lists all extension attributes in your B2C directory. Requires the b2c-extensions-app objectId as the 2nd argument.
Get-B2C-Application : Get the B2C Extensions Application in your B2C directory, so you can retrieve the objectId and pass it to other commands.
Help : Prints this help menu.
Syntax : Gives syntax information for each command, along with examples.

VS Code extension

This is an extension to VS Code that helps with editing and maintaining custom policies.

  • Autocomplete: With the autocomplete feature, you can save your time customizing a B2C policy. The B2C extension provides you the list of policy settings, claims, technical profiles, and claims transformation aggregated from your policy files.
  • Custom policy explorer: This allows you to click the XML element type and select the element you want to open.
  • Go to definition and find all references.
  • Add elements:

**** B2C Add Identity provider technical profile (Shift+Ctrl+1)

**** B2C Add REST API technical profile (Shift+Ctrl+2)

**** B2C Add Claim Type (Shift+Ctrl+3)

**** B2C Add Application Insights (debug mode) (Shift+Ctrl+4)

  • XML schema help: Move your mouse over any XML tag name, to see the description
  • Policy settings: This allows you to manage the values of your Azure AD B2C environments. When you execute the B2C Policy build command, the VS code extension finds and replaces the values of your settings with the ones configured in the policy file, and creates a directory that contains all of your policy files (after the replacement).


There are a few repositories that are useful.

Community content

The above link also provides the policies and the code samples of the Wingtip Games demo. of Azure AD B2C that is deployed here.

These samples are also available here.

It also provides training materials for learning Azure AD B2C with custom policies.

There is also the Woodgrove Groceries demo. that features both Azure AD B2C and Azure AD B2B for external identities.

This demo. is deployed here.

The corresponding administration application is located here.

The custom policies and the relevant sample source code is available here.



Collection here.


Gaining Expertise with Azure AD B2C course for developers.

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