Migrating Custom Policies
Azure AD B2C custom policies are XML-based configuration files that define authentication journeys (User Journeys) as a sequence of OrchestrationSteps, each invoking a TechnicalProfile (e.g. collect input, call REST API, issue token).
Data is held in claims; ClaimsTransformations manipulate them; Preconditions on steps control branching.
Why Migrate to Descope Flows
In Descope, you build the same journeys with our Flows, with: no XML, no ClaimsSchema or ContentDefinitions.
You can branch logic using Condition blocks instead of Preconditions, and token issuance is automatic at flow end.
Scriptlets and the Generic HTTP Connector can cover custom logic and REST calls.
Below we break down a B2C flow step by step and show how each part maps to Descope — so you can translate your own policies the same way.
Example: Sign-in with optional MFA
In this B2C flow, a user signs in with email and password. If the user has an MFA phone number registered, the flow will require SMS OTP; otherwise it will skip MFA.
Then it will issue a JWT with email and name.
B2C Custom Policy Example
The journey is defined in XML. Claims (e.g. email, password, strongAuthenticationPhoneNumber) are declared elsewhere in the policy; steps run in order, with Preconditions controlling whether MFA runs.
Supporting pieces live in other parts of the same (or extended) policy:
- ClaimsSchema for
email,password,strongAuthenticationPhoneNumber,name - TechnicalProfiles for
SelfAsserted-LocalAccountSignin,PhoneFactor-Verify, andJwtIssuer-IssueToken - ContentDefinitions for the HTML of each page
- RelyingParty to select this journey and list OutputClaims for the token.
How it Maps to Descope Flows
The same flow can be built with Descope Flows according to the following steps:
Sign Up or In / Passwordaction — replaces the Self-Asserted local account sign-in TechnicalProfile. User enters email and password; Descope validates and loads the user (and any stored attributes, e.g. phone for MFA).Conditionblock — check whether the user has a phone number (e.g.user.phoneor a custom attribute). One branch goes to MFA, the other skips it (same idea as the B2C Precondition).Sign In OTP / SMSaction (on the "has phone" branch) — replaces thePhoneFactor-VerifyTechnicalProfile. Send and verify the code.Custom Claimsaction — addemailandname(or any flow context values) to the session JWT, analogous to RelyingParty OutputClaims.Endaction — Descope issues the session token automatically; no separate JWTTechnicalProfileis needed.
No XML, no ClaimsSchema, and no ContentDefinitions. Sequencing is the visual order of blocks; the condition replaces Preconditions.
![]()