[object Object]

Microsoft has set a sunset path for Azure AD B2C. Entra External ID is the named successor for external identity scenarios. If your Power Pages site uses B2C today, you are on a migration clock. The Power Pages authentication wiring is similar between the two products, but the contact-record linkage rules are not, and that is where migrations go wrong.

The two identity products

  • Azure AD B2C: separate tenant, custom policies, distinct from your workforce Entra tenant. Used for years for portal identity.
  • Entra External ID: external identity hosted within the workforce Entra tenant as an external collaboration scope. Different config surface, different token shape, different price.

The migration is not lift-and-shift. It is reconfigure-and-relink.

What stays the same

  • The OpenID Connect protocol. Power Pages still consumes an OIDC IdP.
  • The contact-to-identity link via the mspp_externalidentity table or the Contact.AuthenticationType and Contact.Username columns.
  • The Liquid user object for templating.

What changes

  • The tenant scope. External ID lives in your workforce tenant; B2C had its own tenant.
  • The token claim shape. The sub claim and tenant claims differ.
  • User flows vs custom policies. External ID uses user flows; B2C had both. Migration from a custom-policy B2C is more work than migration from a user-flow B2C.
  • Branding and self-service. External ID’s UX surface is different. Pixel will want to revalidate.

The migration plan

A staged plan with parallel run:

  1. Provision External ID in your workforce tenant. Configure a user flow with email + password and any social providers you support.
  2. Configure Power Pages with a new OIDC IdP record pointing to External ID. Keep the B2C IdP record active.
  3. Allow users to sign in with either provider for a transition period.
  4. Bridge the identity link: when a user authenticates via External ID for the first time, look up the existing contact by email and write a new mspp_externalidentity row linking the contact to the new identity.
  5. Notify users to re-enroll via External ID. Track conversion.
  6. Deprecate B2C after the conversion threshold.

Provision External ID

Within the workforce tenant, External ID surfaces as an “External Identities” experience. Create a user flow with the providers you need. Capture the application registration’s client ID, client secret, and the OIDC metadata URL.

{
  "userFlow": "B2C_1A_SignInSignUp",
  "providers": ["EmailWithPassword", "Google", "Microsoft"],
  "claims": ["sub", "email", "given_name", "family_name"],
  "tokenLifetime": 60
}

Wire Power Pages

In Power Pages, add an OIDC IdP. The settings:

  • Authority: the External ID metadata URL.
  • ClientId / ClientSecret: from the app registration.
  • RedirectUri: the Power Pages site’s /signin-oidc endpoint.
  • Scope: openid profile email.
  • IssuerFilter: pin to the External ID issuer to prevent token confusion.

The site settings:

Authentication/OpenIdConnect/ExternalID/Authority = https://<tenant>.ciamlogin.com/<tenant-id>/v2.0
Authentication/OpenIdConnect/ExternalID/ClientId = <client-id>
Authentication/OpenIdConnect/ExternalID/ClientSecret = <secret>
Authentication/OpenIdConnect/ExternalID/RedirectUri = https://<your-site>/signin-oidc
Authentication/OpenIdConnect/ExternalID/Scope = openid profile email
Authentication/OpenIdConnect/ExternalID/CallbackPath = /signin-oidc
Authentication/OpenIdConnect/ExternalID/Issuer = https://<tenant-id>.ciamlogin.com/<tenant-id>/v2.0/

Test with a fresh user. Validate that the contact is created and linked.

The bridge logic

The hard part. When a user authenticates via External ID for the first time, Power Pages will (by default) create a new contact. You do not want a new contact if one already exists from the B2C era. Add a custom Liquid snippet or a pre-authentication Power Automate flow to:

  1. Look up an existing contact by the email claim.
  2. If found and unlinked to External ID, attach the External ID identity as a new mspp_externalidentity row.
  3. If found and already linked to a different External ID identity, raise a conflict — likely a user enrolled twice.
  4. If not found, allow the new contact creation.
// Custom JavaScript in the registration template
const email = portalUser.claims.email;
const existing = await fetch(`/_api/contacts?$filter=emailaddress1 eq '${email}'`);
if (existing.value.length === 1) {
  await fetch('/_api/mspp_externalidentities', {
    method: 'POST',
    body: JSON.stringify({
      'mspp_identityprovidername': 'ExternalID',
      'mspp_username': portalUser.claims.sub,
      '[email protected]': `/contacts(${existing.value[0].contactid})`
    })
  });
}

Validate the bridge against test cases: user with only B2C link, user with no identity link, user with email collision, user already linked.

What about MFA

External ID supports MFA via the same Entra MFA features used for workforce. Configure at the user-flow level. The user experience differs from B2C: External ID surfaces the Entra MFA prompt, which has a different look. Communicate this to users before cutover or they will report it as broken.

See also

Power Pages anonymous access risks — the bridge logic must not bypass anonymous access controls during the unauthenticated lookup step. Use a server-side proxy with a service account, not the anonymous user, to do the email-by-email lookup. (Referencing the security role piece for the broader access-control mental model.)

Pixel notes

The External ID sign-in surface is hosted by Microsoft and themable. Spend a day on the theme — fonts, logo, colors, error copy. The default look is generic and will land for users as “this is not the company I am signing into”. A small branding investment cuts the support tickets in half.

Forge notes

The OIDC token from External ID includes a tid (tenant id) claim. The IssuerFilter setting must include it. If you skip the filter, your portal will accept tokens from any External ID tenant Microsoft chooses to introduce in the future — a subtle confusion attack vector.

Bottom line

  • B2C is winding down; External ID is the named successor.
  • Power Pages supports both via OIDC; the IdP record swap is straightforward.
  • The contact-link bridge is the hard part. Build it server-side with a service identity.
  • Run both providers in parallel during the conversion window.
  • Validate token issuer filters; do not accept tokens from arbitrary External ID tenants.
[object Object]
Share