Custom Entra ID provider: Entra reports sign-in success, but no POST ever reaches /.auth/login/aad/callback
- Dominant language
- No language data
- Stars
- 346
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
# Custom Entra ID provider: Entra reports sign-in success, but no POST ever reaches `/.auth/login/aad/callback`
## Summary
On a **Standard** plan Static Web App with a **custom Microsoft Entra ID provider**,
interactive sign-in never completes. The user authenticates successfully at
Microsoft — Entra's own Sign-in Diagnostic confirms first factor and MFA both
satisfied, with no Conditional Access interruption — but the browser never issues
the `form_post` back to `/.auth/login/aad/callback`, and the user is shown
*"We couldn't sign you in. Please try again."*
The same site works correctly with the **pre-configured** Entra provider
(`/.auth/login/aad` without an `auth` block), using role invitations. Only the
custom registration path fails.
## Environment
| | |
|---|---|
| Plan | Standard |
| Region | Global (no managed Functions API) |
| Deployment | SWA CLI 2.0.10, `swa deploy ./dist --env production` |
| App | static SPA (React 18 / Vite), no API |
| Browsers | Edge 150, Chrome — identical behaviour in both, and in private windows |
## Configuration
`staticwebapp.config.json` (deployed at the root of the output folder; verified
consumed, not served — requesting it does not return the JSON):
```json
{
"auth": {
"identityProviders": {
"azureActiveDirectory": {
"registration": {
"openIdIssuer": "https://login.microsoftonline.com//v2.0",
"clientIdSettingName": "AZURE_CLIENT_ID",
"clientSecretSettingName": "AZURE_CLIENT_SECRET"
}
}
}
},
"routes": [
{ "route": "/.auth/*", "allowedRoles": ["anonymous"] },
{ "route": "/no-access.html", "allowedRoles": ["anonymous"] },
{ "route": "/logout", "redirect": "/.auth/logout" },
{ "route": "/*", "allowedRoles": ["authenticated"] }
],
"responseOverrides": {
"401": { "statusCode": 302, "redirect": "/.auth/login/aad?post_login_redirect_uri=.referrer" },
"403": { "rewrite": "/no-access.html" }
},
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/.auth/*", "/assets/*", "/no-access.html"]
}
}
```
Application settings on the **Production** environment: `AZURE_CLIENT_ID`,
`AZURE_CLIENT_SECRET`.
App registration: **single tenant**; **Web** platform with redirect URI
`https://.azurestaticapps.net/.auth/login/aad/callback`; **ID tokens**
enabled under Implicit grant and hybrid flows; `User.Read` delegated with admin
consent granted.
## Observed behaviour
1. `GET /` → `302` → `/.auth/login/aad?post_login_redirect_uri=/`
2. → `302` → same path with `staticWebAppsAuthNonce`
3. → `302` → `https://login.microsoftonline.com//oauth2/v2.0/authorize?...`
with `response_type=code+id_token`, `response_mode=form_post`,
`redirect_uri=https%3A%2F%2F.azurestaticapps.net%2F.auth%2Flogin%2Faad%2Fcallback`
4. User signs in; MFA completes
5. **No POST to `/.auth/login/aad/callback` appears in the browser network trace**
(DevTools, *Preserve log* enabled, full session captured)
6. Browser shows *"We couldn't sign you in. Please try again."*
## What Entra reports
Sign-in Diagnostic, correlation ID `8b81b7fa-a6af-4178-8a59-d095c23de49c`,
`2026-08-01T13:37:09Z`:
> Based on the information you provided the user … signed into
> . No Conditional Access policies interrupted or blocked the sign-in.
| Date | Auth method | Result |
|---|---|---|
| 2026-08-01T13:37:09Z | Previously satisfied | First factor requirement satisfied by claim in the token |
| 2026-08-01T13:37:09Z | Previously satisfied | MFA requirement satisfied by claim in the token |
`Sign-in logs → Service principal sign-ins` contains **no entries** for this
application — consistent with the authorization code never being redeemed.
## Ruled out, each verified individually
- **ID tokens** enabled (its absence produced a *different*, distinguishable
symptom: an endless MFA loop)
- **Assignment required** set to `No`; also tested with the user explicitly assigned
- **Admin consent** granted for the delegated permission
- **Web redirect URI** present and byte-exact against the `redirect_uri` observed
on the wire
- **Client secret** — every secret deleted and a single fresh one issued, pasted
directly into the Production application setting
- **Both issuer forms** — `https://login.microsoftonline.com//v2.0`,
and the version-1 form `https://login.microsoftonline.com/` with
`userDetailsClaim`. Verified by measurement that this changes the endpoint
called (`/oauth2/v2.0/authorize` vs `/oauth2/authorize`). Neither completes
- **Browser** — Edge and Chrome, normal and private windows, cookies allowed,
tracking prevention lowered
- **Route configuration** — `/.auth/*` allowed anonymously and excluded from
`navigationFallback`; the config is confirmed consumed rather than served
## Expected vs actual
**Expected:** after authentication, Microsoft posts `code`/`id_token` to
`/.auth/login/aad/callback`; the runtime redeems the code and establishes a
session.
**Actual:** authentication succeeds at Entra, the POST never occurs, and the
runtime reports a generic failure with no diagnostic surface — no error code, and
nothing in the tenant's sign-in logs indicating a refusal.
## Questions
1. Is there any way to obtain diagnostics from the Static Web Apps auth runtime
for a failed custom-provider sign-in? The single generic message with no code
makes this undiagnosable from the customer side.
2. Is `response_type=code+id_token` with `response_mode=form_post` expected
against a `/v2.0` issuer, and does anything about that combination require
configuration beyond the documented sample?
## Workaround
Reverted to the pre-configured provider with role invitations, which works
reliably. That costs tenant restriction — the only reason the Standard plan was
purchased.
---
*Tenant, client and host identifiers redacted; available privately. The
correlation ID above is sufficient to locate the sign-in event.*
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with staticwebapp.config.json and reproduce the redirect sequence from /.auth/login/aad through the Entra authorize endpoint, preserving the browser network log. Compare the custom provider flow with the working pre-configured provider and investigate why /.auth/login/aad/callback receives no POST. Done means the callback establishes a session or the runtime exposes actionable diagnostics for the failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, react, vite
- Domain
- authentication, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100