Azure / Azure/static-web-apps

Custom Entra ID provider: Entra reports sign-in success, but no POST ever reaches /.auth/login/aad/callback

Open
#1,784 1 comment 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.