Files
FabledScribe/docs/sso-oauth.md
T
bvandeusen 47e248d9ac docs: restructure documentation into docs/ directory, slim README, add project .mcp.json
- 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>
2026-03-24 21:03:15 -04:00

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).