- README.md: reduced to overview + quick start + links to docs/ - docs/architecture.md: stack, design decisions, data models, key services - docs/configuration.md: all env vars, docker-compose setup, production + security - docs/development.md: dev workflow, CI/CD, migrations, release process - docs/features.md: detailed feature breakdown + keyboard shortcuts - docs/api-keys-and-mcp.md: API key management + Fable MCP install guide - docs/sso-oauth.md: OAuth/OIDC setup (replaces docs/oauth-setup.md) - docs/changelog.md: development history from summary.md - Remove summary.md (content distributed across docs/) - Remove docs/oauth-setup.md (superseded by docs/sso-oauth.md) - .gitignore: add .mcp.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.5 KiB
OAuth / OIDC SSO Setup
Fabled Assistant supports single sign-on via any OpenID Connect provider. This guide covers Authentik, but the same pattern works with Keycloak, Authelia, Zitadel, etc.
1. Create the provider in Authentik
- Log in to the Authentik admin UI.
- Go to Applications → Providers → Create → OAuth2/OpenID Provider.
- Fill in:
- Name:
Fabled Assistant(or whatever you like) - Authorization flow: your default authorization flow
- Client type:
Confidential - Redirect URIs:
https://your-fabled-domain/api/auth/oauth/callback(must matchBASE_URLexactly, including scheme and any path prefix)
- Name:
- Note the generated Client ID and Client Secret.
- Go to Applications → Create, give it a name, and bind it to the provider you just created.
- Note the Issuer URL from the provider detail page — it looks like:
https://auth.example.com/application/o/fabled-assistant/
2. Configure Fabled Assistant
Add the following environment variables to the app service in docker-compose.yml:
services:
app:
environment:
# --- Required ---
OIDC_ISSUER: "https://auth.example.com/application/o/fabled-assistant/"
OIDC_CLIENT_ID: "abc123xyz"
OIDC_CLIENT_SECRET: "supersecret"
# --- Optional ---
# Scopes to request (default: "openid profile email")
# OIDC_SCOPES: "openid profile email"
# Disable local username/password login once SSO is working
# LOCAL_AUTH_ENABLED: "false"
# Make sure BASE_URL matches the redirect URI you registered
BASE_URL: "https://your-fabled-domain"
Docker Secrets alternative: Use
OIDC_CLIENT_SECRET_FILEpointing to a Docker secret file instead ofOIDC_CLIENT_SECRET.
Rebuild and restart:
docker compose up --build -d
3. Verify
- Open
/api/auth/status— it should return:{ "oauth_enabled": true, "local_auth_enabled": true, ... } - Go to the login page — you should see a "Login with [Provider]" button.
- Click it → redirected to provider → authenticate → redirected back → logged in.
- Check
/api/auth/meto confirm your user record.
4. Account Linking
When a user logs in via OAuth for the first time, Fabled checks in this order:
- Existing OAuth sub — returns that user immediately.
- Matching email — if a local account already exists with the same email, the OAuth identity is linked to it automatically. The user retains all their notes and tasks.
- New user — a fresh account is created. Username defaults to
preferred_usernamefrom the provider; if taken,_2,_3, etc. is appended.
5. Disable Local Login (Optional)
Once everyone is using SSO:
LOCAL_AUTH_ENABLED: "false"
The backend will reject any POST /api/auth/login or POST /api/auth/register request with a 403. The login page will only show the SSO button.
Warning: Make sure at least one account has been linked via OAuth before disabling local login, or you will be locked out.
6. Other Providers
| Provider | Issuer URL format |
|---|---|
| Authentik | https://auth.example.com/application/o/<app-slug>/ |
| Keycloak | https://keycloak.example.com/realms/<realm> |
| Authelia | https://auth.example.com |
| Zitadel | https://your-instance.zitadel.cloud |
https://accounts.google.com |
The OIDC discovery endpoint (<issuer>/.well-known/openid-configuration) must be publicly reachable from the Fabled container (server-to-server call at login time).