Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cryguy/hashboard/llms.txt

Use this file to discover all available pages before exploring further.

Hashboard supports OpenID Connect (OIDC) single sign-on as an optional sign-in method for humans. When configured, a Continue with SSO button appears on the login page alongside (or instead of) local username/password. OIDC provisioning is entirely independent of local account registration settings — the IdP governs who can sign in via SSO, and Hashboard provisions a principal on first login automatically.

Required environment variables

Four environment variables must be set to enable OIDC:
VariableDescription
OIDC_ISSUERThe issuer URL of your IdP (must expose /.well-known/openid-configuration).
OIDC_CLIENT_IDThe client ID of the Hashboard application registered in your IdP.
OIDC_CLIENT_SECRETThe client secret for that application.
ORIGINThe public base URL of your Hashboard instance, e.g. https://hashboard.example.com.
ORIGIN is required whenever OIDC is enabled. The SvelteKit adapter-node runtime cannot infer the public-facing origin on its own, so Hashboard uses ORIGIN to construct the absolute redirect_uri sent to your IdP. Without it, the callback URL will be wrong and sign-in will fail.
Any standard OpenID Connect provider works. The example below uses Authentik, but Keycloak, Okta, Auth0, Dex, and any other OIDC-compliant IdP are configured identically — just point the three OIDC_* variables at your provider’s corresponding values.

Provider setup example (Authentik)

In your Authentik admin panel, create an OAuth2/OpenID Connect provider for Hashboard and set the redirect URI to your Hashboard callback URL. Then set the following in your Hashboard .env (or environment):
OIDC_ISSUER=https://authentik.example.com/application/o/hashboard/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
ORIGIN=https://hashboard.example.com
The callback URL to register in your provider:
https://hashboard.example.com/auth/callback

Authentication flow

1

User clicks Continue with SSO

The browser is redirected to GET /auth/oidc. Hashboard generates a PKCE code challenge, a nonce, and a state value, stores them in a short-lived hb_oidc cookie, and redirects to your IdP’s authorization endpoint.
2

IdP authenticates the user

The user authenticates at their IdP (password, MFA, etc.). After success, the IdP redirects back to Hashboard’s callback URL with an authorization code.
3

Hashboard handles the callback

GET /auth/callback exchanges the code for tokens, verifies the nonce, and extracts the OIDC subject (sub) claim. Discovery hits the issuer’s /.well-known/openid-configuration once per process and is then cached — subsequent logins do not incur another round-trip.
4

Principal is upserted

Hashboard looks up the principal by OIDC subject. If no match exists, a new principal is created. If this is the very first human on the instance, that principal is also assigned the super role. If a matching principal already exists, it is returned as-is (display name is not overwritten on repeat logins).
5

Session cookie is set

A new session row is created in the sessions table and the hb_session cookie is set. The user is redirected to /overview (or to the original destination if they were redirected from a protected page).

Discovery caching

oidcConfigured() checks only the environment variables — it never makes a network request. This allows the sign-in page to render immediately without blocking on a round-trip to the IdP. The actual OIDC discovery document is fetched lazily on the first sign-in attempt and cached for the lifetime of the process.

Linking and unlinking OIDC

A single Hashboard account can hold both a local password and an OIDC identity at the same time. This is useful when an instance starts OIDC-only and you later want to add local-password fallback access. Add local login to an OIDC-provisioned account:
curl -X POST https://hashboard.example.com/api/v1/me/credentials \
  -H 'Authorization: Bearer hb_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"username":"alice","password":"correct-horse-battery"}'
Unlink OIDC from your account:
curl -X DELETE https://hashboard.example.com/api/v1/me/oidc \
  -H 'Authorization: Bearer hb_YOUR_TOKEN'
Unlinking OIDC is refused if it is your only sign-in method. You must have local credentials on your account before you can remove your OIDC identity.

Running without OIDC

OIDC is entirely optional. If OIDC_ISSUER, OIDC_CLIENT_ID, and OIDC_CLIENT_SECRET are not set, oidcConfigured() returns false and no OIDC button is rendered on the login page. The GET /auth/oidc and GET /auth/callback routes are effectively inert. The instance runs on local accounts alone.

Build docs developers (and LLMs) love