Skip to content

Fix logout redirect through missing App Service Easy Auth endpoint - #1321

Open
Chad Palmer (chadpalmer) wants to merge 4 commits into
microsoft:Developmentfrom
Xeelee33:fix-logout-route
Open

Fix logout redirect through missing App Service Easy Auth endpoint#1321
Chad Palmer (chadpalmer) wants to merge 4 commits into
microsoft:Developmentfrom
Xeelee33:fix-logout-route

Conversation

@chadpalmer

@chadpalmer Chad Palmer (chadpalmer) commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Fixes #1324

Summary

  • Fix Easy Auth logout detection so logout no longer redirects to /.auth/logout on App Service deployments that are not actually serving App Service Easy Auth. Detection now relies only on the X-MS-CLIENT-PRINCIPAL headers the platform injects into requests it intercepts, instead of trusting the manually configured WEBSITE_AUTH_AAD_ALLOWED_TENANTS application setting.
  • Preserve Easy Auth logout wherever Easy Auth is genuinely active, so the upstream platform session continues to be cleared.
  • Add DISABLE_APP_SERVICE_EASY_AUTH_LOGOUT for deployments where Easy Auth is enabled but /.auth/* is not routed through to the App Service origin, and trace the logout path decision through debug logging.
  • Document logout behavior per environment and the logout 404 troubleshooting steps in the local development guide and example.env.
  • Add regression coverage for Easy Auth local logout, Easy Auth full logout, the reported no-headers case, preservation of Easy Auth logout on a non-production host, and the opt-out flag.
  • Update version metadata, fix documentation, and release notes for v0.260.019.

Scope note

This originally scoped the fix to development mode via IS_DEVELOPMENT. The approach changed while resolving conflicts with Development, because the underlying detection defect affected production deployments as well. See the discussion comment for the full reasoning.

Local development was never affected by the original defect: WEBSITE_HOSTNAME is unset outside App Service, so the check returned early. The reported failure was a deployed non-production App Service.

Validation

  • python -m py_compile application/single_app/config.py application/single_app/route_frontend_authentication.py functional_tests/test_app_service_easy_auth_logout.py functional_tests/test_idle_logout_timeout.py
  • python scripts/check_swagger_routes.py application/single_app/route_frontend_authentication.py
  • python functional_tests/test_app_service_easy_auth_logout.py — 5/5 passing
  • python functional_tests/test_idle_logout_timeout.py — 4/4 passing
  • python functional_tests/route_tests/test_route_blueprint_policy_inventory.py — 6/6 passing
  • python functional_tests/route_tests/test_route_unauthenticated_policy_contract.py — 4/4 passing
  • python functional_tests/route_tests/test_route_policy_test_coverage.py — 2/2 passing
  • python scripts/check_xss_sinks.py --base-sha origin/Development --head-sha HEAD application/single_app/config.py application/single_app/route_frontend_authentication.py
  • python scripts/check_broken_access_control.py --base-sha origin/Development --head-sha HEAD application/single_app/config.py application/single_app/route_frontend_authentication.py
  • git diff --check origin/Development...HEAD

Notes

  • Branch includes latest origin/Development; merge conflicts in config.py and release_notes.md are resolved. Version moved to 0.260.019 because Development had already published its own v0.260.012.
  • Removed a hardcoded customer hostname from the test fixture, since this repository is public.
  • Replaced an exact VERSION = "0.250.004" assertion in test_idle_logout_timeout.py with the repository's assert_app_version_at_least helper. That assertion was already failing on Development and breaks on every version bump.
  • No secrets or credential files were found in the changed file set.
  • UI tests were not run because this change does not modify HTML, CSS, JavaScript, or visible UI behavior.

@chadpalmer

Copy link
Copy Markdown
Contributor Author

Paul Lizer (@paullizer) Bionic711 Another quick update to fix 404 error when the App Service Easy Auth logout endpoint is not available in the development environment.

Resolves the merge conflicts with Development (VERSION and release notes) and
replaces the IS_DEVELOPMENT gate with a correct fix.

Logout redirected to /.auth/logout and returned 404 whenever
WEBSITE_AUTH_AAD_ALLOWED_TENANTS was set without Easy Auth actually running.
That variable is configured by hand per the advanced environment variable
guidance, so it was never evidence Easy Auth was intercepting requests. This
affected production deployments, not just development ones.

Detection now relies only on the X-MS-CLIENT-PRINCIPAL headers App Service
injects into requests it intercepts, so Easy Auth logout is preserved wherever
Easy Auth is genuinely active, including in development.

Adds DISABLE_APP_SERVICE_EASY_AUTH_LOGOUT for deployments where Easy Auth is
active but /.auth/* is not routed to the origin, plus debug logging of the
logout path decision and a Logout Behavior Across Environments section in the
local development guide.

Also removes a customer hostname from the test fixture and replaces an exact
VERSION assertion in the idle logout test with the shared version helper.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer

Copy link
Copy Markdown
Collaborator

Chad Palmer (@chadpalmer), please review my update back, the goal is the same but the way we get there is a little different. Let me know if that works for you and your objectives.

I appreciate taking the time to contribute!

@paullizer

Paul Lizer (paullizer) commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Resolved the merge conflicts with Development and, while in here, changed the approach to the fix. Flagging the reasoning since this rewrites part of Chad Palmer (@chadpalmer)'s work.

Why the approach changed

The 404 is real, but IS_DEVELOPMENT was gating the wrong thing. The actual defect is the line right below it:

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

WEBSITE_AUTH_AAD_ALLOWED_TENANTS is not evidence that Easy Auth is running — application/single_app/example_advance_edit_environment_variables.json tells operators to set it by hand. So any App Service deployment that follows our own advanced setup guidance without enabling Easy Auth hits the same 404, production included. Gating on IS_DEVELOPMENT silenced one environment and left the bug everywhere else.

Two further concerns with the original approach:

  • is_development is documented in LATEST_FEATURES_NAVIGATION_HIDE_PREFERENCE.md as a Latest Features navigation override. Using it to change session termination means anyone setting it to validate that feature also changes how logout behaves.
  • Where a dev environment genuinely runs Easy Auth (our documented standard setup), it disabled platform logout unnecessarily. /logout/local would clear only the Flask session, leaving AppServiceAuthSession and the Entra SSO session alive, so @login_required/login → silent re-auth. Idle timeout inherits that via app.py:1003.

What it does now

Detection relies only on the X-MS-CLIENT-PRINCIPAL* headers App Service injects into requests it actually intercepts. That is a per-request signal, so it fixes the reported case and production, while preserving correct Easy Auth logout wherever Easy Auth is genuinely active — including in development.

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

Worth noting: a localhost developer was never affected, since WEBSITE_HOSTNAME is unset and the function returns early. The reported failure is a deployed non-prod App Service.

Keeping an escape hatch, but a purpose-named one

Row 4 above is the case auto-detection cannot resolve — Easy Auth is live, but a custom domain or gateway does not forward /.auth/*. Added DISABLE_APP_SERVICE_EASY_AUTH_LOGOUT for it. The objection was never "no knob", it was overloading a navigation flag; this one says exactly what it does. It is documented in example.env and in a new "Logout Behavior Across Environments" section in running_simplechat_locally.md, and both non-Easy-Auth paths now log their reason under FLASK_DEBUG=1.

Also in this push

  • Removed a hardcoded customer hostname (oigchat-dev.dhs-oig.gov) from the test fixture — this repo is public.
  • Kept the blueprint + Cosmos stub test harness from this PR. That part was a genuine fix; routes register on the frontend_authentication blueprint, so the previous harness would have raised BuildError.
  • Replaced an exact VERSION = "0.250.004" assertion in test_idle_logout_timeout.py with the repo's assert_app_version_at_least helper. It was already failing on Development and broke again on every version bump.

Version is 0.260.019, since Development had already published its own v0.260.012.

Tests: test_app_service_easy_auth_logout.py 5/5, test_idle_logout_timeout.py 4/4, route policy suites 12/12.

@paullizer Paul Lizer (paullizer) changed the title Fix development logout redirect through missing Easy Auth endpoint Fix logout redirect through missing App Service Easy Auth endpoint Aug 20, 2026
@chadpalmer

Copy link
Copy Markdown
Contributor Author

Chad Palmer (Chad Palmer (@chadpalmer)), please review my update back, the goal is the same but the way we get there is a little different. Let me know if that works for you and your objectives.

I appreciate taking the time to contribute!

Paul Lizer (@paullizer) Your updates look great. I was overly focused on our particular set up. Your improvements are more robust and account for other environments outside of dev. This looks good to go from my perspective. Thanks for taking the time to improve this PR.

@chadpalmer

Copy link
Copy Markdown
Contributor Author

Paul Lizer (@paullizer) I went ahead and fixed the minor merge conflicts. Please let me know if you need anything else from me. Thanks and have a great weekend!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants