From dfc41ada7db2d7458bc2641a80dd16ab96b123e7 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 23 Feb 2026 11:53:34 +0000 Subject: [PATCH] Make account the OAuth authorization server instead of federation All client apps (including federation) now redirect to account for OAuth. Factory excludes account from OAuth client blueprint registration. SSO logout chains through account instead of federation. Co-Authored-By: Claude Opus 4.6 --- infrastructure/factory.py | 9 +++++---- infrastructure/oauth.py | 12 ++++++------ infrastructure/urls.py | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/infrastructure/factory.py b/infrastructure/factory.py index 85553c6..e9b235a 100644 --- a/infrastructure/factory.py +++ b/infrastructure/factory.py @@ -101,8 +101,9 @@ def create_base_app( setup_jinja(app) errors(app) - # Auto-register OAuth client blueprint for non-federation apps - if name != "federation": + # Auto-register OAuth client blueprint for non-account apps + # (account is the OAuth authorization server) + if name != "account": from shared.infrastructure.oauth import create_oauth_blueprint app.register_blueprint(create_oauth_blueprint(name)) @@ -122,8 +123,8 @@ def create_base_app( for fn in before_request_fns: app.before_request(fn) - # Silent SSO: if federation set sso_hint cookie, trigger OAuth once - if name != "federation": + # Silent SSO: if account set sso_hint cookie, trigger OAuth once + if name != "account": from urllib.parse import quote as _quote @app.before_request diff --git a/infrastructure/oauth.py b/infrastructure/oauth.py index a1cb3a5..9c71908 100644 --- a/infrastructure/oauth.py +++ b/infrastructure/oauth.py @@ -1,7 +1,7 @@ -"""OAuth2 client blueprint for non-federation apps. +"""OAuth2 client blueprint for non-account apps. Each client app gets /auth/login, /auth/callback, /auth/logout. -Federation is the OAuth authorization server. +Account is the OAuth authorization server. """ from __future__ import annotations @@ -21,7 +21,7 @@ from sqlalchemy import select from shared.db.session import get_session from shared.models import User from shared.models.oauth_code import OAuthCode -from shared.infrastructure.urls import federation_url, app_url +from shared.infrastructure.urls import account_url, app_url from shared.infrastructure.cart_identity import current_cart_identity from shared.events import emit_activity @@ -41,7 +41,7 @@ def create_oauth_blueprint(app_name: str) -> Blueprint: qsession["oauth_next"] = next_url redirect_uri = app_url(app_name, "/auth/callback") - authorize_url = federation_url( + authorize_url = account_url( f"/auth/oauth/authorize?client_id={app_name}" f"&redirect_uri={redirect_uri}" f"&state={state}" @@ -136,7 +136,7 @@ def create_oauth_blueprint(app_name: str) -> Blueprint: qsession.pop(SESSION_USER_KEY, None) qsession.pop("cart_sid", None) qsession.pop("sso_checked", None) - # Redirect through federation to clear the SSO session too - return redirect(federation_url("/auth/sso-logout/")) + # Redirect through account to clear the SSO session too + return redirect(account_url("/auth/sso-logout/")) return bp diff --git a/infrastructure/urls.py b/infrastructure/urls.py index ae67351..bfa591b 100644 --- a/infrastructure/urls.py +++ b/infrastructure/urls.py @@ -72,8 +72,8 @@ def market_product_url(product_slug: str, suffix: str = "", market_place=None) - def login_url(next_url: str = "") -> str: from quart import current_app - # Federation handles login directly (magic link flow) - if current_app.name == "federation": + # Account handles login directly (magic link flow — it's the OAuth server) + if current_app.name == "account": base = "/auth/login/" params: list[str] = [] if next_url: @@ -86,7 +86,7 @@ def login_url(next_url: str = "") -> str: return f"{base}?{'&'.join(params)}" return base - # Client apps: local /auth/login triggers OAuth redirect to federation + # Client apps: local /auth/login triggers OAuth redirect to account base = "/auth/login/" if next_url: return f"{base}?next={quote(next_url, safe='')}"