Skip to content

Logout returns 404 at /.auth/logout when App Service Easy Auth is not actually enabled #1324

Open

Description

@paullizer

Summary

Logout can redirect to /.auth/logout?post_logout_redirect_uri=%2Flogin and return a 404 on Azure App Service deployments that are not actually serving App Service Easy Auth.

This was first reported on a development custom domain, but it is not limited to development environments. Any deployment matching the same conditions is affected, including production.

Root Cause

_use_app_service_easy_auth_logout() in application/single_app/route_frontend_authentication.py treated the WEBSITE_AUTH_AAD_ALLOWED_TENANTS environment variable as proof that Easy Auth was intercepting requests:

return any(easy_auth_headers) or bool(os.getenv('WEBSITE_AUTH_AAD_ALLOWED_TENANTS'))

That variable is not a reliable Easy Auth signal. SimpleChat's own advanced configuration guidance in application/single_app/example_advance_edit_environment_variables.json instructs operators to set it by hand:

{ "name": "WEBSITE_AUTH_AAD_ALLOWED_TENANTS", "value": "<your-allowed-tenant-id>", "slotSetting": false }

So any deployment that followed those documented instructions on App Service, without Easy Auth actually enabled, was misdetected. Logout then redirected to a platform endpoint the App Service was not serving, producing the 404.

A secondary case exists where Easy Auth genuinely is enabled but /.auth/* is not routed through to the App Service origin, for example behind a custom domain, gateway, or Front Door with restrictive path routing. Per-request detection cannot distinguish that case, so it needs an explicit opt-out.

Impact

  • User-initiated logout (/logout, /logout/local) returns a 404 instead of completing.
  • Idle-timeout logout inherits the same behavior, since it routes through local_logout (app.py:1003).
  • Affects production as well as non-production deployments.

Not affected: local development. WEBSITE_HOSTNAME is unset outside App Service, so the check returns early. The originally reported failure was a deployed non-production App Service, not a localhost session.

Expected Behavior

Environment Easy Auth headers Expected logout path
Local machine (python app.py) No Local logout
App Service, Easy Auth enabled Yes Easy Auth logout via /.auth/logout
App Service, Easy Auth not enabled No Local logout
Easy Auth enabled, /.auth/* not routed Yes Local logout via explicit opt-out

Resolution

Detection now relies only on the X-MS-CLIENT-PRINCIPAL, X-MS-CLIENT-PRINCIPAL-ID, and X-MS-CLIENT-PRINCIPAL-NAME headers that App Service injects into requests it actually intercepts. This is a per-request signal, so it corrects both development and production while preserving Easy Auth logout wherever Easy Auth is genuinely active.

Supporting changes:

  • Added DISABLE_APP_SERVICE_EASY_AUTH_LOGOUT for the unroutable-/.auth/* case.
  • Added debug logging of the logout path decision, visible with FLASK_DEBUG=1.
  • Documented behavior per environment and logout-404 troubleshooting in docs/explanation/running_simplechat_locally.md and application/single_app/example.env.
  • Removed a hardcoded customer hostname from the test fixture, since this repository is public.

Validation

  • functional_tests/test_app_service_easy_auth_logout.py — 5/5 passing
  • functional_tests/test_idle_logout_timeout.py — 4/4 passing
  • functional_tests/route_tests/ — 12/12 passing
  • scripts/check_swagger_routes.py, scripts/check_xss_sinks.py, scripts/check_broken_access_control.py — all passing

References

Activity

  1. added
    bugSomething isn't working
    P2Priority 2: important, scheduled after P0/P1
    on Aug 20, 2026
  2. paullizer commented on Aug 20, 2026

    @paullizer
    CollaboratorAuthor

    Tried to assign this to Chad Palmer (@chadpalmer) as the reporter and author of the fix in #1321, but GitHub rejected it: he is not a repository collaborator, and GitHub only allows assignment to collaborators or users who have commented on the issue.

    Mentioning him here instead so he is notified and shows in the participants list. Once he comments, or if he is added as a collaborator, the assignment will go through.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Priority 2: important, scheduled after P0/P1bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions