Mode

Choose your learning path

Switch between Developer Mode and End User Mode at any time. Your choice is remembered in this browser.

Microsoft Entra External ID

Native Authentication for External Identities

A direct, CORS-friendly API surface for building fully custom sign-in, sign-up, MFA, and password reset flows without redirecting users away from your application.

Explore the API
Native Auth APIs MSAL Popup & Redirect MFA & Registration Token Inspection Operator Mode

Detailed Documentation

Native Auth comes first in this lab, then compare MSAL Popup and Browser Redirect implementation trade-offs.

Guided Journey

Recommended order: Native Auth โ†’ MSAL Popup โ†’ MSAL Redirect. Steps are softly gated, but you can skip and continue anytime.

What is Native Authentication?

Native Authentication lets your application call Entra External ID endpoints directly using standard OAuth 2.0 grants โ€” no hosted login page required. Your UI stays in full control at every step.

๐Ÿ”‘

Full UI Control

Design and brand every step of the authentication journey. No redirects, no hosted pages, no compromise on user experience.

๐Ÿ“ก

Direct API Access

Calls are made through a local CORS proxy in development. Each step returns a continuation token that drives the next request.

๐Ÿ”’

MFA & Registration

Handles MFA challenges (OTP via email/SMS), strong method registration, and self-service password reset โ€” all within the same API contract.

๐Ÿ”„

Token Renewal

Use the issued refresh token to silently renew sessions via the same token endpoint, extending user sessions without re-authentication.

API Reference

All endpoints are relative to your tenant authority: https://{subdomain}.ciamlogin.com/{tenantId}

POST
/oauth2/v2.0/initiate
Start a sign-in flow and obtain the first continuation token
โ–ผ

Parameters

ParamRequiredDescription
client_idโœ“App registration client ID
usernameโœ“User's email / UPN
challenge_typeโœ“Space-separated list: password oob redirect. Must include redirect as required fallback.

Response

FieldDescription
continuation_tokenOpaque token to pass to /challenge
challenge_typeredirect when app must fall back to hosted login

Common Errors

Error / SuberrorCause
user_not_foundNo account with that username
nativeauthapi_disabledNative Auth not enabled for tenant
invalid_clientIncorrect client_id or app not registered
{
  "client_id": "...",
  "username": "user@contoso.com",
  "challenge_type": "password oob redirect"
}
POST
/oauth2/v2.0/challenge
Select the authentication method for this user session
โ–ผ

Parameters

ParamRequiredDescription
client_idโœ“App registration client ID
continuation_tokenโœ“Token from /initiate or /token
challenge_typeโœ“Supported types: password oob redirect
idMethod ID from /introspect (for MFA challenge selection)

Response

FieldDescription
challenge_typepassword, oob, or redirect
continuation_tokenUpdated token for next step
challenge_channelOOB delivery channel (email)
challenge_target_labelMasked delivery address (e.g. a***@c.com)
code_lengthExpected OTP length
{
  "challenge_type": "oob",
  "challenge_channel": "email",
  "challenge_target_label": "u***@contoso.com",
  "code_length": 8,
  "continuation_token": "..."
}
POST
/oauth2/v2.0/token
Verify credential and issue access, ID, and refresh tokens
โ–ผ

Parameters

ParamRequiredDescription
client_idโœ“App registration client ID
grant_typeโœ“See grant types table below
continuation_tokenโœ“Current continuation token (most flows)
scopeโœ“openid offline_access profile
passwordUser's password (grant_type=password)
oobOTP code (grant_type=oob or mfa_oob)
refresh_tokenExisting refresh token (grant_type=refresh_token)

Grant Types

grant_typeWhen to use
passwordFirst-factor password authentication
oobFirst-factor email OTP authentication
mfa_oobMFA second factor (email OTP)
continuation_tokenComplete registration or pending flow
attributesSupply sign-up custom attributes
refresh_tokenSilent session renewal with stored token

Token Response

FieldDescription
access_tokenJWT; use for API authorization
id_tokenJWT; user identity claims (openid scope required)
refresh_tokenOpaque; for session renewal (offline_access scope required)
expires_inAccess token lifetime in seconds
scopeGranted scopes

Conditional Responses

SuberrorMeaningNext step
mfa_requiredMFA step requiredCall /introspect then /challenge with method ID
registration_requiredMust enroll MFA methodCall /register/v1.0/introspect
invalid_oob_valueWrong OTP enteredShow error, allow retry
password_too_weakPassword policy violationShow policy requirements
POST
/oauth2/v2.0/introspect
Discover registered MFA methods for the user
โ–ผ

Parameters

ParamRequiredDescription
client_idโœ“App registration client ID
continuation_tokenโœ“Token received after mfa_required suberror

Response

FieldDescription
continuation_tokenFresh token to use in /challenge
methods[]Array of method objects
methods[].idMethod ID to pass to /challenge as id param
methods[].challenge_typee.g. oob
methods[].challenge_channele.g. email
methods[].login_hintMasked target for display
POST ร—3
/register/v1.0/{introspect ยท challenge ยท continue}
Enroll a strong authentication method during sign-up or first sign-in
โ–ผ

/register/v1.0/introspect

Lists enrollable MFA methods. The continuation token comes from a registration_required response from /oauth2/v2.0/token.

ParamRequired
client_idโœ“
continuation_tokenโœ“

/register/v1.0/challenge

Send enrollment challenge OTP to the user's target.

ParamRequired
client_idโœ“
continuation_tokenโœ“
challenge_typeโœ“
challenge_targetโœ“

/register/v1.0/continue

Submit the OTP to complete enrollment and return to the token flow.

ParamRequired
client_idโœ“
continuation_tokenโœ“
grant_typeโœ“ (oob)
oob
Note: After successful /register/v1.0/continue, call /oauth2/v2.0/token again with grant_type=continuation_token to complete the full authentication and receive tokens.

Authentication Flows

Each flow is a sequence of API calls connected by continuation tokens. Every step must receive and forward the latest token.

Sign-In

Email + Password

  1. POST /initiate โ€” start sign-in, obtain continuation token
  2. POST /challenge โ€” Entra selects authentication method
  3. POST /token with grant_type=password โ€” verify credential
  4. โœ“ Receive access_token, id_token, refresh_token
If /token returns mfa_required โ†’ continue with MFA flow below.
MFA Extension

Multi-Factor Authentication

  1. Triggered when /token returns suberror=mfa_required
  2. POST /introspect โ€” get list of enrolled MFA methods
  3. User selects method from the returned list
  4. POST /challenge with selected method id โ€” delivery OTP
  5. User enters received OTP code
  6. POST /token with grant_type=mfa_oob + oob value
  7. โœ“ Receive final token set
Registration

Strong Method Enrollment

  1. Triggered when /token returns suberror=registration_required
  2. POST /register/v1.0/introspect โ€” list enrollable methods
  3. User selects method to enroll
  4. POST /register/v1.0/challenge โ€” send enrollment OTP
  5. User enters received OTP code
  6. POST /register/v1.0/continue with grant_type=oob + oob value
  7. POST /token with grant_type=continuation_token โ€” finalize
  8. โœ“ Receive token set
Renewal

Session Renewal (Refresh Token)

  1. Store refresh_token from initial sign-in token response
  2. POST /token with grant_type=refresh_token + stored token
  3. โœ“ Receive new access_token, id_token, and optionally a rotated refresh_token
Refresh tokens expire or are revoked. Always handle failure and prompt re-authentication if renewal fails.
SSPR

Self-Service Password Reset

  1. POST /resetpassword/v1.0/start โ€” initiate with username
  2. POST /resetpassword/v1.0/challenge โ€” deliver OTP
  3. User enters OTP code
  4. POST /resetpassword/v1.0/continue โ€” verify OTP
  5. POST /resetpassword/v1.0/submit โ€” submit new password
  6. GET /resetpassword/v1.0/poll_completion โ€” poll until success
  7. โœ“ Password updated; prompt user to sign in
Redirect Fallback

Redirect Fallback

  1. Any endpoint may return challenge_type=redirect
  2. This is a control response, not a transport error
  3. Your app must fall back to a hosted sign-in page (MSAL popup or redirect)
  4. Always advertise redirect in your challenge_type list to satisfy API requirements
This demo handles redirect fallback by switching to MSAL popup or redirect flows.

Key Concepts

๐Ÿ”— Continuation Token

An opaque, short-lived token that connects sequential API calls within the same flow. You must propagate the most recent continuation token to each subsequent request. Tokens are endpoint-sequence specific โ€” using one out of order will fail.

๐ŸŽฏ Challenge Types

Values that declare which authentication method is requested or supported. Always include redirect in your advertised list as a required fallback. Common values: password, oob, redirect.

๐Ÿ” Grant Types

The credential mechanism used at the token endpoint. The correct grant type depends on flow stage: password for first-factor, oob/mfa_oob for OTP steps, refresh_token for renewal, continuation_token after registration.

๐Ÿ“‹ Error Contract

All error responses include error, error_description, suberror (for branching), trace_id, and correlation_id. Always capture trace_id for support escalation. Treat expired_token as a signal to restart the flow.

๐Ÿšฆ Scopes

Request openid offline_access as a minimum. Add profile for name/email claims in the ID token. Add Microsoft Graph scopes (e.g. User.Read) to authorize Graph API calls with the resulting access token.

๐Ÿ›ก๏ธ CORS Proxy

Native Auth endpoints do not support browser CORS. A local forwarding proxy (cors.js, running on port 3001) transparently proxies all /api/* requests from the browser to the Entra endpoints during development.

Best Practices & Error Handling

โœ“ Do
  • Always include redirect in challenge_type to comply with API requirements
  • Capture trace_id and correlation_id from every error response for support diagnostics
  • Handle expired_token by restarting the current flow from /initiate
  • Implement bounded retry (max 3 attempts) for invalid_oob_value
  • Treat challenge_type=redirect as a legitimate control path, not a failure
  • Store refresh tokens in sessionStorage, not localStorage
  • Request offline_access scope at token step to receive a refresh token
โœ— Don't
  • Omit redirect from challenge_type โ€” API may reject unsupported challenges
  • Reuse a continuation token after it has been consumed by a successful call
  • Assume a continuation token is valid after navigating away โ€” restart if unsure
  • Retry interaction_required or consent_required errors silently โ€” they require user action
  • Store credentials or tokens in plaintext files or source control
  • Call Native Auth endpoints directly from the browser without a CORS proxy in development

Common Error Codes

errorsuberrorMeaningRecovery
invalid_grantmfa_requiredMFA second factor requiredCall /introspect, then /challenge with method ID
invalid_grantregistration_requiredUser must enroll MFA methodStart /register/v1.0 flow
invalid_grantinvalid_oob_valueWrong OTP enteredShow error, allow bounded retry
invalid_grantpassword_too_weakPassword fails policyShow policy requirements
invalid_grantexpired_tokenContinuation token expiredRestart flow from /initiate
invalid_clientnativeauthapi_disabledNative Auth not enabledEnable in Entra portal tenant settings
user_not_foundโ€”No account with that usernameCheck username, offer sign-up
unauthorized_clientโ€”App not configured for this flowCheck app registration in Entra portal

Production Hardening Checklist

This starter is optimized for learning. Validate these items before production rollout.

  • Keep raw token values hidden in production and remove demo-mode token reveal controls.
  • Prefer secure, server-backed session/token handling over browser persistence for sensitive workloads.
  • Review redirect URIs, token scopes, and consent requirements across all environments.
  • Log and monitor only safe diagnostics: never log token values or full auth payloads.
  • Validate accessibility, error recovery, and browser compatibility for your supported audience.

MSAL Popup Flow

Popup keeps app context and feels seamless, but can be blocked by browser settings and restrictive environments.

Popup Mechanics

How it works

  1. App calls loginPopup() with configured scopes.
  2. Browser opens auth popup window.
  3. User completes auth and consent in popup.
  4. Popup closes and parent window receives tokens.
Edge Cases

What can fail

  • Pop-up blockers or strict enterprise browser policies.
  • Safari and iOS behavior differences around window focus.
  • User closes popup before completion.

MSAL Browser Redirect Flow

Redirect is broadly compatible and reliable when popup is blocked, but causes full-page navigation away from app state.

Redirect Mechanics

How it works

  1. App calls loginRedirect().
  2. Browser navigates to Microsoft identity endpoint.
  3. After sign-in, browser returns to configured redirect URI.
  4. App processes response in handleRedirectPromise().
Edge Cases

What to handle

  • Lost transient UI state if not persisted before redirect.
  • Return-route and deep-link continuity for complex SPAs.
  • Multi-tab flows and stale interaction state.

Popup vs Redirect: Deep Comparison

Use this matrix as an architecture decision aid for your product and platform constraints.

Dimension MSAL Popup MSAL Redirect
UX continuity Strong continuity in same page context. Full page navigation breaks continuity temporarily.
Browser constraints Can fail with popup blockers or strict policies. More reliable across restrictive browser settings.
Security & token handling Same token semantics; fewer route re-entry concerns. Requires careful redirect URI and state handling.
Error recoverability Inline recovery feels immediate. Recovery often handled after navigation roundtrip.
Implementation complexity Simpler UX integration, more popup fallbacks needed. Predictable flow, but more app-state restoration logic.
Accessibility Popup context switch can confuse some assistive tech users. Single-window navigation can be easier to follow.

Ready to explore the flows end-to-end?

Sign in with this demo or use the Postman collection to test each Native Auth endpoint step by step.

Download Postman Collection

Verify your identity

Choose a verification method

Register MFA Method

Choose a method to register

Enter verification code

Add Phone Method

Register a phone factor for sign-in

Create account

Register a customer account with Microsoft Entra Native Auth.

Reset password

Use Microsoft Entra Native Auth self-service password reset.

Find your email

Enter the phone number saved on your account.

Error diagnostics

Operator user detail

Claim diff