OIDC Authentication#
Homepage (v2.0+) supports OpenID Connect (OIDC) as an authentication gate, implemented via NextAuth.js. When HOMEPAGE_OIDC_ISSUER, HOMEPAGE_OIDC_CLIENT_ID, and HOMEPAGE_OIDC_CLIENT_SECRET are all provided, OIDC mode activates and overrides password-based login . All app pages and /api routes — except /api/healthcheck, /api/config/custom.css, and the NextAuth/auth paths — require a valid session when auth is enabled .
Authorization is fully delegated to the identity provider. Homepage grants access to any identity the provider authorizes for this client; configure group membership, access policies, or client assignments at the provider level, not in Homepage .
The primary implementation files are:
| File | Role |
|---|---|
src/pages/api/auth/[...nextauth].js | NextAuth handler — provider registration, session strategy (jwt), startup validation |
src/utils/env.js | applyNextAuthEnv() / isAuthEnabled() — maps HOMEPAGE_* vars to NextAuth internals |
src/middleware.js | Route protection — enforces JWT session on all non-public paths |
Configuration#
All three HOMEPAGE_OIDC_* variables must be set together — providing any partial subset throws a startup error .
| Variable | Required | Notes |
|---|---|---|
HOMEPAGE_AUTH_ENABLED | Yes | Must be true |
HOMEPAGE_AUTH_SECRET | Yes | Min 32 chars; mapped to NEXTAUTH_SECRET. Generate with openssl rand -base64 32 |
HOMEPAGE_EXTERNAL_URL | Yes | Absolute HTTP(S) URL — scheme + host + port — mapped to NEXTAUTH_URL |
HOMEPAGE_OIDC_ISSUER | Yes | Provider base URL; trailing slashes stripped automatically |
HOMEPAGE_OIDC_CLIENT_ID | Yes | Client ID registered at the provider |
HOMEPAGE_OIDC_CLIENT_SECRET | Yes | Client secret |
HOMEPAGE_OIDC_NAME | No | Sign-in button label (default: Homepage OIDC) |
HOMEPAGE_OIDC_SCOPE | No | OAuth scopes (default: openid email profile) |
HOMEPAGE_OIDC_AUTO_LOGIN | No | true skips the sign-in page and redirects straight to the provider |
Set your OIDC provider's redirect / callback URI to:
https://<your-homepage-url>/api/auth/callback/homepage-oidc
Homepage registers the provider with idToken: true and checks: ["pkce", "state", "nonce"] . Secure cookies are enabled automatically when HOMEPAGE_EXTERNAL_URL uses https: .
Tip: With
HOMEPAGE_OIDC_AUTO_LOGIN=true, bypass the automatic redirect for troubleshooting by visiting/auth/signin?autologin=0.
Supplying Secrets Securely#
Avoid embedding raw secrets in compose files. Use Docker Swarm secrets or env_file files — but be aware that Docker does not strip literal quote characters, so HOMEPAGE_OIDC_CLIENT_SECRET="abc" will pass "abc" (with quotes) as the secret value .
For variable substitution inside Homepage config files, see HOMEPAGE_VAR_* and HOMEPAGE_FILE_* .
Troubleshooting#
Verbose error logs#
The latest Docker image tag may log only a generic OAUTH_CALLBACK_ERROR without the underlying cause. Switch to the :dev tag to get verbose error messages including the specific rejection reason .
JWT algorithm mismatch (unexpected JWT alg received, expected RS256, got: HS256)#
Homepage requires RS256-signed ID tokens (idToken: true) . Some providers — notably Authentik — default to HS256.
Fix (Authentik): Go to System → Certificates, generate a new RSA certificate-key pair, then edit the Homepage provider, set Signing Key to that certificate, and save .
Client authentication failure (invalid_client)#
The authorization code exchange succeeds (provider redirects back) but the backend token-endpoint call is rejected. Common causes :
- Wrong client type — the provider client must be Confidential, not Public.
- Secret mismatch — copy the secret from the provider's detail page (not the list view, which may truncate). Avoid quoting the value in
env_file. - Wrong issuer scope — in Authentik, credentials are scoped per provider; verify
HOMEPAGE_OIDC_ISSUERmatches the exact provider slug holding the registered client.
Check the provider's own token-endpoint logs for the authoritative rejection reason.
TLS / certificate trust (SIGNIN_OAUTH_ERROR)#
Node.js uses its own TLS trust store, not the container's system /etc/ssl/certs/. If your OIDC issuer uses a private or self-signed CA, Homepage cannot fetch the discovery document .
Diagnose by running inside the container:
docker exec homepage node -e \
'const i=process.env.HOMEPAGE_OIDC_ISSUER.replace(/\/+$/,""); \
fetch(i+"/.well-known/openid-configuration").then(r=>console.log(r.status,r.statusText)).catch(console.error)'
Fix — mount your root CA and set NODE_EXTRA_CA_CERTS:
volumes:
- ./rootCA.crt:/usr/local/share/ca-certificates/rootCA.crt:ro
environment:
NODE_EXTRA_CA_CERTS: /usr/local/share/ca-certificates/rootCA.crt
Mounting /etc/ssl/certs/ from the host is not sufficient; Node.js ignores that path .
Cookie / state validation failures#
State, PKCE, and nonce are stored in cookies scoped to HOMEPAGE_EXTERNAL_URL. If the URL in the browser doesn't exactly match (scheme, hostname, port), cookies are absent on callback and the flow silently fails. Verify HOMEPAGE_EXTERNAL_URL equals the URL shown in the browser's address bar exactly .
Further Reading#
- Homepage authentication docs — official configuration reference
- Discussion: Unable to get Authentik OIDC working — community troubleshooting thread
- Discussion: OIDC login OAuthCallback errors — algorithm mismatch and TLS walkthrough