mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 14:44:48 +00:00
- Introduced encoding and decoding of OAuth state to include tenant metadata, allowing the gateway to route callbacks without hard-coded tenant slugs. - Updated the AuthController to handle social account linking and sign-in with compatibility for legacy paths. - Refactored redirect URI construction to simplify tenant slug handling. - Enhanced documentation to reflect changes in the OAuth flow and state management. Signed-off-by: Innei <tukon479@gmail.com>
3.2 KiB
3.2 KiB
OAuth Gateway
Multi-tenant OAuth callback router that lets every identity provider point to a single domain
(auth.afilmory.art, for example) while keeping the actual Better Auth handlers inside each tenant
subdomain.
How It Works
- Better Auth (running inside
be/apps/core) wraps the OAuthstatewith the tenant slug. - Providers always redirect to the fixed URL
https://auth.afilmory.art/api/auth/callback/{provider}. - The gateway unwraps
state, restores the inner Better Auth state, and issues a 302 redirect tohttps://<slug>.afilmory.art/api/auth/callback/{provider}(preservingcode,state, etc.).
Because the gateway only rewrites the callback target, it does not interact with provider APIs or tokens. This keeps configuration simple (single callback URL in GitHub/Google) while ensuring tenant sessions are still created on the correct host.
Development
pnpm --filter @afilmory/oauth-gateway dev
The service starts on http://0.0.0.0:8790 by default.
Environment Variables
| Variable | Default | Description |
|---|---|---|
AUTH_GATEWAY_HOST |
0.0.0.0 |
Interface to bind. |
AUTH_GATEWAY_PORT |
8790 |
Port to listen on. |
AUTH_GATEWAY_BASE_DOMAIN |
afilmory.art |
Root domain used when constructing tenant hosts. |
AUTH_GATEWAY_CALLBACK_BASE_PATH |
/api/auth/callback |
Base path that the providers call. |
AUTH_GATEWAY_FORCE_HTTPS |
true |
Forces redirects to https unless the host looks like localhost. |
AUTH_GATEWAY_ALLOW_CUSTOM_HOST |
false |
Allow requests to pass an explicit targetHost query parameter. |
AUTH_GATEWAY_ROOT_SLUG |
root |
Slug treated as the apex (no subdomain). |
AUTH_GATEWAY_STATE_SECRET |
none (required) | HMAC secret for decoding wrapped state values (fallbacks to CONFIG_ENCRYPTION_KEY). |
Callback Contract
GET /api/auth/callback/:provider
Query parameters:
state— wrapped gateway state containing the tenant slug and inner Better Auth state.tenantSlug(legacy) ortenant— optional slug fallback whenstateis not wrapped.targetHost— explicit host override (opt-in viaALLOW_CUSTOM_HOST).- All other query parameters (
code, etc.) are forwarded verbatim.
Example redirect produced by the gateway:
https://auth.afilmory.art/api/auth/callback/github?code=...&state=<wrapped>
⮕ 302 → https://innei.afilmory.art/api/auth/callback/github?code=...&state=<inner>
This service is intentionally stateless so it can be deployed behind a simple load balancer.