Iframe-based SSO logout (tolerates dead apps)
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 48s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-23 12:21:54 +00:00
parent 80c4400ae2
commit 4e8e6bab61
3 changed files with 37 additions and 13 deletions

View File

@@ -201,7 +201,6 @@ def register(url_prefix="/auth"):
@auth_bp.post("/logout/")
async def logout():
qsession.pop(SESSION_USER_KEY, None)
# Chain through all client apps to clear their sessions too
return redirect(url_for("auth.sso_logout"))
@auth_bp.get("/clear/")
@@ -214,21 +213,25 @@ def register(url_prefix="/auth"):
@auth_bp.get("/sso-logout/")
async def sso_logout():
"""SSO logout: clear account session, then chain through all client
apps so each clears its own first-party session cookie."""
"""SSO logout: clear account session, then render a page with hidden
iframes that clear each client app's first-party session cookie.
Tolerates dead apps — iframes that fail are silently ignored."""
qsession.pop(SESSION_USER_KEY, None)
from shared.infrastructure.urls import blog_url, market_url, cart_url, events_url, federation_url
from urllib.parse import quote
# Build redirect chain: blog → market → cart → events → federation → blog home
final = blog_url("/")
chain = federation_url(f"/auth/sso-clear?next={quote(final, safe='')}")
chain = events_url(f"/auth/sso-clear?next={quote(chain, safe='')}")
chain = cart_url(f"/auth/sso-clear?next={quote(chain, safe='')}")
chain = market_url(f"/auth/sso-clear?next={quote(chain, safe='')}")
chain = blog_url(f"/auth/sso-clear?next={quote(chain, safe='')}")
clear_urls = [
blog_url("/auth/sso-clear"),
market_url("/auth/sso-clear"),
cart_url("/auth/sso-clear"),
events_url("/auth/sso-clear"),
federation_url("/auth/sso-clear"),
]
return redirect(chain)
return await render_template(
"auth/signing_out.html",
clear_urls=clear_urls,
final_url=blog_url("/"),
)
return auth_bp