SSO (OIDC)
Ony.ai supports single sign-on via any OpenID Connect provider (Authentik, Keycloak, Google Workspace, Azure AD, Okta). It uses the authorization-code flow with PKCE and verifies the ID token’s signature, issuer, audience, expiry, and nonce. When SSO is configured, a “Sign in with SSO” button appears on the login page. The variables below are documented alongside the rest in the configuration reference.
How it works
Section titled “How it works”Dashboard ──/auth/oidc/login──▶ Ony API ──redirect──▶ IdP (login) │Dashboard ◀──/sso#token=…────── Ony API ◀──callback──────┘/api/v1/auth/oidc/loginbuilds the authorize URL (PKCE S256, state, nonce), stores that transient data in a short-lived, signed, HttpOnly cookie, and redirects to the IdP.- The IdP authenticates the user and redirects back to
/api/v1/auth/oidc/callback. - Ony.ai validates
stateagainst the cookie, exchanges the code for tokens, verifies the ID token, then links an existing account by email (or JIT-provisions one), mints a session, and hands it to the SPA.
No token or PKCE verifier is ever exposed in a logged URL: the flow data lives in the cookie and the session token is delivered in the URL fragment.
Configure
Section titled “Configure”Set these in .env (see .env.example) and register the callback URL with your IdP:
| Variable | Meaning |
|---|---|
ONY_OIDC_ISSUER |
Discovery base URL, e.g. https://auth.example.com/application/o/ony/ |
ONY_OIDC_CLIENT_ID / ONY_OIDC_CLIENT_SECRET |
The client credentials from your IdP |
ONY_OIDC_SCOPES |
Default openid email profile |
ONY_OIDC_ALLOWED_DOMAINS |
Email domains allowed to auto-create an account (empty = no JIT) |
ONY_OIDC_ADMIN_GROUP |
Users whose groups claim contains this value become admins |
ONY_OIDC_GROUPS_CLAIM |
Claim to read groups from (default groups) |
Callback URL to register with the IdP: <ONY_PUBLIC_BASE_URL>/api/v1/auth/oidc/callback
Example: Authentik (self-hosted, fits a Proxmox homelab)
Section titled “Example: Authentik (self-hosted, fits a Proxmox homelab)”- In Authentik, create an OAuth2/OpenID Provider: redirect URI
https://ony.example.com/api/v1/auth/oidc/callback(your Ony.ai server’s domain), signing key default, scopesopenid email profile(add agroupsscope or claim if you want role mapping). - Create an Application bound to that provider; note its slug. The issuer is
https://<authentik-host>/application/o/<slug>/. - Put the client id and secret and the issuer in
.env, setONY_OIDC_ALLOWED_DOMAINS=yourcompany.com, and optionallyONY_OIDC_ADMIN_GROUP=ony-admins. - Restart the API and open the dashboard: “Sign in with SSO” is now available.
Provisioning and roles
Section titled “Provisioning and roles”- Existing users are matched by email and signed in with their current role. SSO never silently changes an existing user’s privileges.
- New users are JIT-created only if their email domain is allowlisted, joining your organization as a
member (or admin if they are in
ONY_OIDC_ADMIN_GROUP). Each JIT creation is recorded in the audit chain asuser.sso_provisioned. - The IdP must assert a verified email (
email_verifiednot false); Ony.ai rejects the login otherwise.
- SAML is not supported yet; use your IdP’s OIDC endpoint (Okta, Azure AD, and Google all expose one).
- SSO-only accounts have no password. Keep at least one password (or separate-IdP) admin as a break-glass path in case the IdP is unavailable.
See hardening for the surrounding production checklist, and data handling for what the IdP claims are stored as.