For fifteen years the answer to “where does the user type their password” has been the same: not on your page. The redirect flow sends them to Microsoft, they authenticate on a domain you don’t control, and you get back a token. Native Authentication, now generally available for Entra External ID, throws that out. Your single-page app collects the credential, calls an API, and drives the whole sign-in itself. No redirect, no popup, no leaving your React component.
That is genuinely useful and slightly alarming, and both things are true at once.
What actually changed
Standard MSAL.js does redirect- or popup-based OIDC. The browser hands off to Entra’s hosted pages, the user does their thing, PKCE protects the code exchange, and MSAL caches the token. You never see the password. Native Authentication replaces the hosted UI with a set of API calls the SDK wraps. You render your own sign-up and sign-in screens, and the SDK orchestrates the challenge/response steps behind them: start the flow, submit an email, submit an OTP or password, satisfy an MFA challenge, receive tokens.
Supported methods at GA are email one-time passcode, password, and MFA on top of either. PKCE still applies. It’s External ID only — this does not exist in workforce Entra ID tenants, and it is not meant to. If you’re authenticating employees, keep using the redirect flow.
A minimal sign-in looks roughly like this:
No redirect. The user never leaves the app. That’s the pitch.
The pushback
Skeptic: You just told me the password now gets typed into a text box that my JavaScript owns. That’s the thing we spent a decade telling people never to build.
Correct, and this is the part the launch blog glides past. With the redirect flow, credential entry happens on login.microsoftonline.com or the CIAM equivalent. Your app’s compromised npm dependency, your XSS bug, your rogue browser extension — none of them are in the room when the password is typed. Native Authentication puts them all in the room. A supply-chain compromise in your bundle can now read plaintext credentials, not just steal a token.
Skeptic: So it’s strictly worse.
No — it’s a different risk profile you now own directly. The redirect flow’s protection is real but it’s borrowed. Native Auth hands you the responsibility and expects you to earn it: a hard content security policy, ruthless dependency hygiene, no third-party scripts anywhere near the auth surface. Do that and you’re fine. Skip it and you’ve built a credential harvester with good UX.
Skeptic: And the tokens land in the browser regardless.
They do — same as any SPA. Access and refresh tokens live in the browser context, which means XSS is game over either way. Native Auth doesn’t make that worse; it just removes the one place credentials weren’t exposed. Treat token storage the way you already should: short-lived access tokens, refresh handled by the SDK, and assume anything in localStorage is one injection away from exfiltration.
What it doesn’t do
Read the limitations before you scope the sprint. There’s no social IDP passthrough in native flows — if you want “Sign in with Google,” that still needs a redirect, so a mixed app runs both models. Custom authentication extensions and the richer policy surface you might expect from the old B2C world aren’t the same story here. And it’s External ID, full stop; pointing this at a workforce tenant is a non-starter.
Verify your setup where it actually lives: the app registration and the user flow under External Identities in the Entra admin center, with native authentication enabled on the flow. If the flow isn’t configured for it, the SDK calls fail closed — which, for once, is the right default.
Ship it for consumer apps where the redirect bounce genuinely hurt conversion. Just don’t ship it with a lazy CSP and thirty transitive dependencies you’ve never read.
