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 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-23 11:53:34 +00:00
parent 60cd08adc9
commit dfc41ada7d
3 changed files with 14 additions and 13 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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='')}"