Tips and tricks for working with custom policies in Azure AD B2C
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 Signin policy
There is a custom SignUpOrSignin policy but no Signin only policy.
You can achieve this by setting SignUp to “False”.
Customise screen UI
These settings turn the feature on / off.
The default is “true” = feature on.
- 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”.
<! — <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. →
You can alter the message texts by “localising” English to English! i.e.
<Item Key=”DisplayName”>Signin and Signup with KMSI</Item>
<LocalizedResourcesReference Language=”en” LocalizedResourcesReferenceId=”api.localaccountsignup.en” />
<SupportedLanguages DefaultLanguage=”en” MergeBehavior=”ReplaceAll”>
<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>
A neat trick is to set the reply_uri to “https://jwt.ms”.
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.
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).
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”.
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”/>
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 “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.
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.
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 (https://b2csamlrp.azurewebsites.net/SP/) 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.
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.
- The starter pack
- Azure AD B2C Custom Policies with the Identity Experience Framework (IEF)
- Azure Active Directory B2C: Custom CIAM User Journeys
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.