47e248d9ac
- 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>
96 lines
3.5 KiB
Markdown
96 lines
3.5 KiB
Markdown
# 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
|
|
|
|
1. Log in to the Authentik admin UI.
|
|
2. Go to **Applications → Providers → Create → OAuth2/OpenID Provider**.
|
|
3. 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 match `BASE_URL` exactly, including scheme and any path prefix)*
|
|
4. Note the generated **Client ID** and **Client Secret**.
|
|
5. Go to **Applications → Create**, give it a name, and bind it to the provider you just created.
|
|
6. 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`:
|
|
|
|
```yaml
|
|
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_FILE` pointing to a Docker secret file instead of `OIDC_CLIENT_SECRET`.
|
|
|
|
Rebuild and restart:
|
|
|
|
```bash
|
|
docker compose up --build -d
|
|
```
|
|
|
|
## 3. Verify
|
|
|
|
1. Open `/api/auth/status` — it should return:
|
|
```json
|
|
{ "oauth_enabled": true, "local_auth_enabled": true, ... }
|
|
```
|
|
2. Go to the login page — you should see a **"Login with [Provider]"** button.
|
|
3. Click it → redirected to provider → authenticate → redirected back → logged in.
|
|
4. Check `/api/auth/me` to confirm your user record.
|
|
|
|
## 4. Account Linking
|
|
|
|
When a user logs in via OAuth for the first time, Fabled checks in this order:
|
|
|
|
1. **Existing OAuth sub** — returns that user immediately.
|
|
2. **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.
|
|
3. **New user** — a fresh account is created. Username defaults to `preferred_username` from the provider; if taken, `_2`, `_3`, etc. is appended.
|
|
|
|
## 5. Disable Local Login (Optional)
|
|
|
|
Once everyone is using SSO:
|
|
|
|
```yaml
|
|
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` |
|
|
| Google | `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).
|