Commit Graph

14 Commits

Author SHA1 Message Date
giles
748d28e657 Set blog_did = account_did — one device identity across all apps
Callback adopts account's device_id by overwriting g.device_id,
so the factory after_request sets {app}_did cookie to account's value.
Simplifies factory check: g.device_id IS the account_did, no need
to read _account_did from session separately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:11:24 +00:00
giles
cad528d732 Device-id SSO: account sets did, signals login via Redis
- Factory: set {name}_did cookie for all apps (including account)
  via before_request/after_request hooks (g.device_id always available)
- Factory: _check_auth_state checks did_auth:{account_did} in Redis
  to override stale "not logged in" cache when account login detected
- OAuth: removed _ensure_device_cookie (moved to factory), callback
  stores account_did from authorize redirect in session
- OAuth: login uses g.device_id, logout clears _account_did

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:57:40 +00:00
giles
c4590d1442 Replace propagation chain + check-device with prompt=none OAuth handshake
Client apps now do a silent OAuth round-trip (prompt=none) to account on
first visit. If user is logged in on account, they get silently logged in.
If not, the result is cached (5 min) to avoid repeated handshakes.

Grant verification now uses direct DB query instead of aiohttp HTTP calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:40:58 +00:00
giles
de93dfdc73 Device cookie + internal endpoint for auth state detection
Each client app sets a persistent first-party device cookie ({app}_did).
On each request:
- Logged in: verify grant via account internal endpoint (cached 60s)
- Not logged in + device cookie: check-device endpoint detects if user
  logged in since last grant revocation → triggers OAuth automatically
No cross-domain cookies. No propagation chain. Each app checks independently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:50:43 +00:00
giles
6bb26522a1 Add OAuth grants for per-device session revocation
- OAuthGrant model tracks each client authorization, tied to the
  account session (issuer_session) that issued it
- OAuth authorize creates grant + code together
- Client apps store grant_token in session, verify via account's
  internal /auth/internal/verify-grant endpoint (Redis-cached 60s)
- Account logout revokes only grants from that device's session
- Replaces iframe-based logout with server-side grant revocation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:30:08 +00:00
giles
9a637c6227 sso-clear returns 204 for iframe-based logout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:21:14 +00:00
giles
a93a456ac5 Remove sso_hint cookie, add sso-clear logout chain
sso_hint on .rose-ash.com was blocked by Safari ITP — the exact
problem we're solving. Replaced with redirect chain: account logout
chains through each client app's /auth/sso-clear to clear all
first-party sessions without any cross-domain cookies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:17:22 +00:00
giles
dfc41ada7d 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>
2026-02-23 11:53:34 +00:00
giles
60cd08adc9 Add /auth/clear endpoint to reset session cookies
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:44:47 +00:00
giles
d50f01d41f Logout: redirect through federation sso-logout to clear all sessions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:31:44 +00:00
giles
bfd8d55f27 Silent SSO via sso_hint cookie
- Federation sets sso_hint=1 on .rose-ash.com after magic link login
- Client apps: before_request checks sso_hint, triggers silent OAuth
  once per session (sso_checked flag prevents loops)
- Logout clears sso_hint cookie on all apps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:23:26 +00:00
giles
d0a5170cd9 Fix logout: redirect to blog home to avoid re-auth loop
Account's / requires login, so redirecting there after logout
triggers silent OAuth re-authentication. Blog home is safe.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:15:14 +00:00
giles
ea35e040e7 Fix OAuth authorize URL: include /auth prefix
The federation auth blueprint is mounted at /auth, so the authorize
endpoint is /auth/oauth/authorize, not /oauth/authorize.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:25:46 +00:00
giles
46f44f6171 OAuth SSO infrastructure + account app support
- OAuthCode model + migration for authorization code flow
- OAuth client blueprint (auto-registered for non-federation apps)
- Per-app first-party session cookies (fixes Safari ITP)
- /oauth/authorize endpoint support in URL helpers
- account_url() helper + Jinja global
- Templates: federation_url('/auth/...') → account_url('/...')
- Widget registry: account page links use account_url

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:55:27 +00:00