# OAuth / OIDC SSO Setup (Authentik) 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 in Authentik BASE_URL: "https://your-fabled-domain" ``` > **Docker Secrets alternative:** Instead of `OIDC_CLIENT_SECRET`, you can use > `OIDC_CLIENT_SECRET_FILE` pointing to a Docker secret file. 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 Authentik"** button. 3. Click it → you are redirected to Authentik → authenticate → redirected back to Fabled → 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 address, the OAuth identity is linked to it automatically. The user retains all their notes and tasks. 3. **New user** — a fresh account is created. The username defaults to the `preferred_username` claim from the provider; if taken, `_2`, `_3`, etc. is appended. --- ## 5. Disable local login (optional) Once everyone is using SSO you can hide the username/password form: ```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).