Title: Static Web Apps: /.auth/logout with the aad provider never returns to the app (end-session request has no client_id or id_token_hint)

Gavin Neal 0 Reputation points
2026-10-21T23:33:42.9966667+00:00

Setup

  • Azure Static Web Apps, Standard plan, custom domain.
  • Two providers in staticwebapp.config.json:
  • customOpenIdConnectProviders "customer" (Microsoft Entra External ID / ciamlogin.com), loginParameterNames ["prompt=login"]
  • azureActiveDirectory ("aad"), openIdIssuer https://login.microsoftonline.com/common/v2.0, loginParameters ["prompt=login"]
  • Workforce app registration: multi-tenant + personal accounts, ID tokens enabled. Redirect URIs include /.auth/login/aad/callback, /login and /.auth/logout/complete on the custom domain.

Problem 1: aad sign-out never returns

Sign in via /.auth/login/aad, then navigate to /.auth/logout?post_logout_redirect_uri=/login.

  1. /.auth/logout?post_logout_redirect_uri=/login → 302
  2. /.auth/logout?post_logout_redirect_uri=/.auth/logout/complete&staticWebAppsAuthNonce=… → 302
  3. login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=https://<our-domain>/.auth/logout/complete → 200 This request contains ONLY post_logout_redirect_uri: no client_id, no id_token_hint.
  4. Microsoft shows "You signed out of your account" (once: "Hmm... we're having trouble signing you out") and never redirects back.

Result: /.auth/logout/complete is never reached and /.auth/me still returns the aad principal. Reproduced repeatedly in clean Chrome Incognito windows. One run did return to the app, and we can't explain the difference.

The same flow with the custom OIDC provider returns correctly: ciamlogin logout → /.auth/logout/complete → /login.

Problem 2: interrupted custom OIDC logout falls back to aad

If the user closes the tab at External ID's "Pick an account" during logout, the next /.auth/logout redirects hop 2 to login.microsoftonline.com/common/oauth2/v2.0/authorize with redirect_uri /.auth/login/aad/callback (an aad sign-in challenge), while /.auth/me still returns the customer principal. Both SWA cookies are sent, and deleting StaticWebAppsAuthContextCookie doesn't help. A fresh /.auth/login/customer sign-in clears the condition.

Questions

  1. Why does SWA's aad end-session request omit client_id/id_token_hint, and what configuration makes Microsoft redirect back to /.auth/logout/complete? Is /.auth/logout/aad/callback or a front-channel logout URL required?
  2. How does SWA choose the provider during a repeated logout, and why does it fall back to aad?
  3. What is the supported way to end an SWA session when the identity provider's end-session page doesn't redirect back? We don't call /.auth/logout/complete directly and want to avoid /.auth/purge.
Azure Static Web Apps
Azure Static Web Apps

An Azure service that provides streamlined full-stack web app development.

0 comments No comments

1 answer

Sort by: Most helpful
  1. AI answer

    2026-10-21T23:34:55.8533333+00:00

    Static Web Apps managed authentication does not retain the ID token needed to send id_token_hint, so no staticwebapp.config.json or app-registration setting can make its current /.auth/logout request include that parameter; use /.auth/logout for the SWA session, and move logout into an authentication layer you control if reliable upstream Entra logout is mandatory.^1^

    1. Why the Entra logout does not return

    The missing id_token_hint is a known SWA implementation limitation. The SWA team explains that its distributed architecture does not store tokens as App Service does, so it cannot supply the hint during logout. The issue remains open.^1^

    For Microsoft identity platform logout:

    • post_logout_redirect_uri is supported without id_token_hint.
    • It must exactly match a redirect URI registered for the application.
    • logout_hint is optional and primarily suppresses account selection.^2^

    Your captured request already contains the documented minimum redirect parameter, and /.auth/logout/complete is registered. Therefore, there is no additional SWA setting known to force Entra to return when that request stalls. Adding client_id, logout_hint, or id_token_hint to your initial /.auth/logout URL will not make SWA forward them unless the product explicitly supports doing so.

    The documented SWA invocation remains:

    <a href="/.auth/logout?post_logout_redirect_uri=/login">
      Sign out
    </a>
    

    SWA documents /.auth/logout as the logout route and post_logout_redirect_uri as the way to select the final page.^3^

    Callback and front-channel URLs

    For custom authentication, register the documented provider callback:

    https://<YOUR_SITE>/.auth/logout/aad/callback
    

    SWA owns that route; do not create a page there. The corresponding login callback is:

    https://<YOUR_SITE>/.auth/login/aad/callback
    

    These are the documented callback destinations for custom providers.^4^

    However, adding the logout callback is not expected to change the trace you captured: SWA is explicitly sending /.auth/logout/complete as post_logout_redirect_uri, and Entra never navigates back.

    A front-channel logout URL is not the return URL for RP-initiated logout. It supports single sign-out by letting Entra notify applications—typically in a hidden iframe—to clear their own sessions. It does not add an ID-token hint to SWA’s outbound request or replace /.auth/logout/complete.^5^

    2. Why an interrupted customer logout falls through to aad

    The public SWA contract documents:

    • Provider-specific login: /.auth/login/<provider>
    • Provider-neutral logout: /.auth/logout
    • User state: /.auth/me^4^

    It does not document an algorithm for selecting a provider when an earlier logout transaction is interrupted, nor does it document falling back from a custom OIDC provider to aad. Because /.auth/me still reports customer while SWA starts /.auth/login/aad, this should not be treated as expected provider selection behavior.

    Deleting StaticWebAppsAuthContextCookie has already ruled out the obvious client-side transaction-cookie workaround. Capture the following for an Azure support case:

    1. UTC timestamp for a failing run.
    2. Complete redirect chain, with query values and secrets redacted.
    3. Cookie names and domains—not cookie values.
    4. /.auth/me result immediately before and after the interrupted logout.
    5. The deployed auth.identityProviders configuration with secrets removed.
    6. A comparison trace from the successful custom-provider logout.

    Also run Azure portal → Static Web App → Diagnose and solve problems → Authentication and Authorization. SWA diagnostics include custom-authentication configuration and historical diagnostic data.^6^

    3. Supported session-ending choices

    1. SWA-managed logout: Continue using /.auth/logout. Do not call /.auth/logout/complete directly; it is the completion target, not the logout initiator.^3^
    2. If the IdP never returns: SWA exposes no documented second endpoint that safely resumes or completes that interrupted transaction. /.auth/purge is for removing stored personal data, not normal logout, so avoiding it is correct.^3^
    3. If deterministic Entra sign-out is required: Handle authentication outside SWA managed authentication—for example, with MSAL in the SPA or an authentication backend—so the application owns the ID token/account context and can issue logoutRedirect with the account and post-logout URI.^5^ This is an architectural change; SWA cannot currently be configured to expose its managed ID token for that purpose.

    References

    1. Auth: id_token_hint not sent to End Session Endpoint
    2. OpenID Connect on the Microsoft identity platform
    3. Authenticate and authorize Static Web Apps | Microsoft Learn
    4. Custom authentication in Azure Static Web Apps
    5. Signing out users
    6. Azure Static Web Apps diagnostics overview
    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.