# 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//` | | Keycloak | `https://keycloak.example.com/realms/` | | Authelia | `https://auth.example.com` | | Zitadel | `https://your-instance.zitadel.cloud` | | Google | `https://accounts.google.com` | The OIDC discovery endpoint (`/.well-known/openid-configuration`) must be publicly reachable from the Fabled container (server-to-server call at login time).