Single Sign-On (SSO)
Minepanel can delegate authentication to any standard OpenID Connect (OIDC) provider: Authentik, Authelia, Keycloak, Zitadel, Google, and others. This centralizes access for a homelab and lets you optionally disable username/password login so only SSO is allowed.
How it works
Minepanel acts as a confidential OIDC client (BFF pattern):
- The user clicks Sign in with {provider} on the login screen.
- The backend redirects to your provider with PKCE + state + nonce.
- After authenticating, the provider redirects back to the backend callback.
- The backend validates the
id_tokenand issues its own Minepanel session (the samehttpOnlycookies used by password login).
The identity provider only authenticates; roles and permissions are still managed inside Minepanel.
Provisioning
- On the first SSO login a Minepanel user is created, matched by
suband then by email. - If there are no users yet, the first person to sign in via SSO becomes the admin with full access (bootstrap).
- Every subsequent SSO user is created as a regular
USERwith no permissions until an admin grants access under Settings → Access.
Configuration
Configure from the panel (recommended)
OIDC can now be managed from Settings → Integrations (admin only). Values are stored encrypted in the database and take effect without a restart. The environment variables below still work as a fallback/default; a value set in the panel overrides the matching variable. Secrets are write-only in the UI — the client secret is never sent back to the browser.
SSO can also be configured with environment variables. It is enabled only when OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET and OIDC_REDIRECT_URI are all set (in the panel or .env).
| Variable | Required | Description |
|---|---|---|
OIDC_ISSUER | yes | Issuer URL (the backend auto-discovers endpoints from it) |
OIDC_CLIENT_ID | yes | Client ID from your provider |
OIDC_CLIENT_SECRET | yes | Client secret (kept server-side only) |
OIDC_REDIRECT_URI | yes | Backend callback, e.g. https://api.example.com/auth/oidc/callback |
OIDC_SCOPES | no | Defaults to openid email profile |
OIDC_PROVIDER_NAME | no | Label shown on the login button (default SSO) |
OIDC_DISABLE_PASSWORD_LOGIN | no | true hides and blocks password login (SSO only) |
The redirect URI points to the backend, not the frontend.
With Docker, just add these variables to your .env file — the Compose files load optional settings from .env automatically (no need to edit docker-compose.yml).
Example: Authentik
- In Authentik create an OAuth2/OpenID Provider:
- Redirect URI:
https://api.example.com/auth/oidc/callback - Signing key: default; scopes:
openid,email,profile.
- Redirect URI:
- Create an Application bound to that provider and assign the users/groups that may access Minepanel (Authentik enforces who can reach the app).
- Copy the Client ID and Client Secret and set:
OIDC_ISSUER=https://auth.example.com/application/o/minepanel/
OIDC_CLIENT_ID=...
OIDC_CLIENT_SECRET=...
OIDC_REDIRECT_URI=https://api.example.com/auth/oidc/callback
OIDC_PROVIDER_NAME=AuthentikExample: Google
OIDC_ISSUER=https://accounts.google.com
OIDC_CLIENT_ID=...
OIDC_CLIENT_SECRET=...
OIDC_REDIRECT_URI=https://api.example.com/auth/oidc/callback
OIDC_PROVIDER_NAME=GoogleSSO-only mode
Set OIDC_DISABLE_PASSWORD_LOGIN=true to hide the username/password form and the password-reset flow. The backend also rejects POST /auth/login and POST /auth/setup-admin so the restriction cannot be bypassed from the API. The first admin is still bootstrapped through the first SSO login.
This flag is ignored unless SSO is fully configured, so a misconfiguration cannot lock you out of the panel.
Troubleshooting
- Button not shown: confirm all four required
OIDC_*variables are set and restart the backend. CheckGET /auth/setup-statusreturnssso.enabled: true. - Redirected back with
?ssoError=1: the callback failed (state/nonce mismatch, expired transaction, clock skew, or wrong redirect URI). VerifyOIDC_REDIRECT_URImatches the provider exactly and that backend and provider clocks are in sync. disabledaccount: the matched Minepanel user is inactive; re-enable it under Settings → Access.
