# Step 6 — Single Sign-On (SSO) **Track:** With AI (Beginner) **Time for this step:** 3–5 hours SSO (Single Sign-On) means one login for everything. After this step, you will log in with your Authentik account once and every service will recognize you automatically. No more logging in to each service separately. --- ## How SSO Works (Plain English) Without SSO: ``` You → Grafana login page → type username + password → logged in to Grafana You → Forgejo login page → type username + password → logged in to Forgejo (repeat for every service) ``` With SSO: ``` You → Grafana "Sign in with Authentik" button → Authentik asks for login (once, or already remembered) → Authentik tells Grafana "this is kenpat, let them in" → Logged in to Grafana You → Forgejo "Sign in with Authentik" → Already logged into Authentik → instantly logged in to Forgejo ``` The technology behind this is called **OAuth2** and **OIDC**. For now, you do not need to know the details — just follow the steps. (The concepts file explains it deeply if you are curious: [concepts/oauth2-oidc.md](../../concepts/oauth2-oidc.md)) --- ## The Process for Each Service For every service, you do the same three things: **In Authentik:** 1. Create an OAuth2 Provider for the service 2. Create an Application that links to that Provider 3. (Optional) Add a Policy to restrict who can access it **In the service:** 4. Enter the Authentik credentials (client ID, client secret, URLs) Your AI will guide you through each one. Use this prompt template: > "I want to configure SSO for [service name] using Authentik as the OIDC provider. > The service is at https://[service].yourdomain.com. Walk me through: > 1. Creating an OAuth2 provider in Authentik's admin panel > 2. What redirect URI to use > 3. How to configure the service to use Authentik for login" --- ## SSO for Grafana **In Authentik admin panel (auth.yourdomain.com/if/admin/):** 1. Go to **Applications → Providers → Create** 2. Choose **OAuth2/OpenID Provider** 3. Name: `Grafana` 4. Client type: `Confidential` 5. Redirect URIs: `https://grafana.yourdomain.com/login/generic_oauth` 6. Scopes: openid, email, profile 7. Save — note the **Client ID** and **Client Secret** 8. Go to **Applications → Applications → Create** 9. Name: `Grafana`, Slug: `grafana` 10. Provider: select the Grafana provider you just created 11. Save **In Grafana's `.env` or `docker-compose.yml` environment:** ``` GF_AUTH_GENERIC_OAUTH_ENABLED=true GF_AUTH_GENERIC_OAUTH_NAME=Authentik GF_AUTH_GENERIC_OAUTH_CLIENT_ID=paste-client-id-here GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=paste-client-secret-here GF_AUTH_GENERIC_OAUTH_SCOPES=openid email profile GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://auth.yourdomain.com/application/o/authorize/ GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://auth.yourdomain.com/application/o/token/ GF_AUTH_GENERIC_OAUTH_API_URL=https://auth.yourdomain.com/application/o/userinfo/ GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(groups, 'homelab-admin') && 'Admin' || 'Viewer' ``` Restart Grafana: `docker compose restart grafana` Visit `grafana.yourdomain.com` — you should see a "Sign in with Authentik" button. --- ## SSO for Forgejo **In Authentik:** Create an OAuth2 Provider with: - Redirect URI: `https://gitforge.yourdomain.com/user/oauth2/authentik/callback` **In Forgejo:** - Site Administration → Authentication Sources → Add Authentication Source - Type: OAuth2 - Name: `authentik` - OAuth2 Provider: OpenID Connect - Client ID and Secret from Authentik - OpenID Connect Discovery URL: `https://auth.yourdomain.com/application/o/forgejo/.well-known/openid-configuration` **Ask your AI:** "Walk me through adding an OAuth2 authentication source in Forgejo's admin panel." --- ## SSO for Karakeep **Important:** Karakeep uses NextAuth.js internally. The redirect URI is NOT the usual `/callback/authentik` — it is `/api/auth/callback/custom`. **In Authentik:** Create OAuth2 Provider with: - Redirect URI: `https://links.yourdomain.com/api/auth/callback/custom` **In Karakeep's environment:** ``` NEXTAUTH_URL=https://links.yourdomain.com NEXTAUTH_SECRET=generate-a-random-secret OAUTH_WELLKNOWN_URL=https://auth.yourdomain.com/application/o/karakeep/.well-known/openid-configuration OAUTH_CLIENT_ID=paste-client-id OAUTH_CLIENT_SECRET=paste-client-secret OAUTH_PROVIDER_NAME=Authentik OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING=true ``` --- ## SSO for Kavita **In Authentik:** Create OAuth2 Provider with: - Redirect URI: `https://kavita.yourdomain.com/api/auth/callback` **In Kavita:** Go to Settings → OIDC (must be done through the UI, not by editing files): - Authority: `https://auth.yourdomain.com/application/o/kavita/` ← trailing slash required - Client ID and Client Secret from Authentik - Enabled: on **Critical:** The trailing slash in the Authority URL is required. Without it, Kavita gives an "issuer does not match" error. --- ## SSO for Open WebUI **In Authentik:** Create OAuth2 Provider with: - Redirect URI: `https://ai.yourdomain.com/oauth/oidc/callback` **In Open WebUI's environment:** ``` ENABLE_OAUTH_SIGNUP=true OAUTH_PROVIDER_NAME=Authentik OPENID_PROVIDER_URL=https://auth.yourdomain.com/application/o/openwebui/.well-known/openid-configuration OAUTH_CLIENT_ID=paste-client-id OAUTH_CLIENT_SECRET=paste-client-secret ``` --- ## SSO for BookStack **In Authentik:** Create OAuth2 Provider with: - Redirect URI: `https://wiki.yourdomain.com/oidc/callback` - Issuer mode: **Per Provider** (important — set this in Authentik's provider settings) **In BookStack's `.env`:** ``` AUTH_METHOD=oidc AUTH_AUTO_INITIATE=false OIDC_NAME=Authentik OIDC_DISPLAY_NAME_CLAIMS=name OIDC_CLIENT_ID=paste-client-id OIDC_CLIENT_SECRET=paste-client-secret OIDC_ISSUER=https://auth.yourdomain.com/application/o/bookstack/ OIDC_ISSUER_DISCOVER=true ``` After setting this up, the BookStack cache directory needs to be writable: ```bash docker exec bookstack chown -R abc:users /config/www/framework/cache/ docker compose restart bookstack ``` --- ## SSO for Portainer **In Authentik:** Create OAuth2 Provider with: - Redirect URI: `https://portainer.yourdomain.com` **In Portainer:** Settings → Authentication → OAuth: - Provider: Custom - Client ID and Secret from Authentik - Authorization URL: `https://auth.yourdomain.com/application/o/authorize/` - Token URL: `https://auth.yourdomain.com/application/o/token/` - Userinfo URL: `https://auth.yourdomain.com/application/o/userinfo/` - Redirect URL: `https://portainer.yourdomain.com` - Scopes: `openid email profile` **Security note:** In Authentik, add a Policy Binding to the Portainer application to restrict access to your admin group only. This prevents anyone with an Authentik account from accessing the Docker management panel. --- ## Restricting Access by Group (Security) For sensitive services like Portainer, you want only administrators to access them: 1. In Authentik, go to **Directory → Groups → Create** 2. Name: `homelab-admin` 3. Add yourself to this group 4. Go to **Applications → Applications → [Portainer] → Policy Bindings** 5. Add a binding: Group → `homelab-admin` → Allow Now only members of `homelab-admin` can use the Portainer application through SSO. --- ## Checkpoint Test SSO for each service: - [ ] Grafana — "Sign in with Authentik" works - [ ] Forgejo — OAuth2 login works - [ ] Karakeep — SSO login works - [ ] Kavita — "Sign in with Authentik" works - [ ] Open WebUI — SSO login works - [ ] BookStack — OIDC login works - [ ] Portainer — OAuth login works If any fail, check the error message and ask your AI: "I'm getting this error when signing in to [service] with Authentik: [paste the error]. What does it mean and how do I fix it?" --- **Next:** [Step 7 — Cloud Failover (kscloud1)](07-cloud-failover.md)