Definite on-prem supports Sign in with Google via OIDC. Anyone in your Google Workspace domain can log in by clicking a button, and one named user is auto-provisioned as the first admin. This guide is cloud-agnostic — once your deployment is up on AWS, GCP, or Azure, the SSO setup is the same.Documentation Index
Fetch the complete documentation index at: https://docs.definite.app/llms.txt
Use this file to discover all available pages before exploring further.
What’s supported
- OIDC Authorization Code flow with PKCE against Google.
- ID token validation (signature via Google’s JWKS, plus
iss/aud/exp/noncechecks). - Domain restriction via Google’s
hdclaim — non-matching accounts are refused. - First login auto-provisions a user. The
initialAdminEmailvalue lets one specific email land asadminon first login, so a fresh deployment can bootstrap its first human admin via SSO. - Password login keeps working side-by-side. The built-in
fi@definite.appsupport user is unaffected.
What’s not supported yet
- Group → role mapping from Google Workspace groups. Everyone lands as
defaultRole(orinitialAdminEmaillands asadmin). - Auto-linking an existing password user to their Google account on first login. See Email collisions below.
- Generic / non-Google OIDC providers (Okta, Entra, etc.). The helm schema reserves
auth.oidc.provider: genericas an extension point but the API refuses to start with it today. - MFA / step-up auth — Google’s own 2FA covers this.
- RP-initiated logout. Signing out of Definite does not sign the user out of Google.
Step 1 — Create a Google OAuth 2.0 Client ID
In the Google Cloud Console, in the same GCP project (or any project — they don’t have to match the project hosting your deployment):Configure the OAuth consent screen
APIs & Services → OAuth consent screen.Pick Internal if the deployment is restricted to your Workspace org (the common case). With External you have to add every login email as a test user until the consent screen is verified.Fill in:
- App name: e.g.
Definite (internal) - User support email: an address in your Workspace
- Developer contact: another address in your Workspace
openid, .../auth/userinfo.email, .../auth/userinfo.profile. Definite does not need any other Google API.Create the OAuth Client ID
APIs & Services → Credentials → Create credentials → OAuth client ID.
- Application type: Web application
-
Name: e.g.
Definite on-prem -
Authorized redirect URIs: add exactly the deployment’s callback URL:
The hostname is whatever you set in your helm values under
deployment.hostname. Google only honors exact matches —redirect_uri_mismatchis the most common setup mistake. If your deployment is reachable at multiple URLs, add a redirect URI for each.
Step 2 — Wire helm values
Add this block to theconfig.yaml you pass to definite init (or your values.yaml overlay):
When
auth.mode: oidc, both clientId and clientSecret are required — the chart fails fast with a clear message if either is empty. Keep clientSecret out of version control; pass it via an env var substitution in config.yaml (e.g. clientSecret: ${OIDC_CLIENT_SECRET}) or a secret-management tool.Step 3 — Apply and verify
https://<your-hostname>/login in a browser. You should see a Sign in with Google button above the email/password form. Click it. Google’s consent screen opens. Accept, and you’re bounced back to Definite logged in.
If initialAdminEmail matched the email you signed in with, you’ll have the admin role and full Settings access immediately.
How it works under the hood
- State + PKCE. Both are generated server-side and stored in an HttpOnly, short-lived (10 min) cookie. The callback validates the round-trip against the cookie before doing anything else — a missing or tampered cookie is a 400.
- Token validation. The ID token signature is verified against Google’s JWKS, fetched via the discovery document. Claims checked:
iss,aud,exp,sub,nonce,email_verified. IfallowedDomainsis non-empty,hdmust match one of them. - Session token delivery. On success, the API 302s the browser to
/auth/oidc-complete#token=...— the token lives in the URL fragment, not the query string, so it never reaches nginx access logs. A small client page reads it out, writes it tolocalStorage, and forwards on.
Email collisions
If someone signs in via Google with an email that already belongs to a password-mode user (auth_provider = 'local'), the OIDC login is refused with HTTP 409 and a clear message. Definite doesn’t auto-link the two accounts — silently associating a Google identity with a pre-existing password row would be a quiet security regression.
To resolve, an admin must either:
- Delete or deactivate the existing password user (Settings → Members), then have the Google user retry the SSO login. They get a fresh row with
auth_provider = 'google'and the role fromdefaultRole/initialAdminEmail. - Flip the existing row to SSO by running
UPDATE definite.users SET auth_provider='google' WHERE email='...';against the app database. This preserves the user’s history (queries, automations, audit-log attribution) but disables password login on that row.
An admin-friendly path (
definite admin link-sso <email> and a Settings UI action) is on the roadmap so you don’t have to delete or run SQL by hand. Track issue #291.Audit log
Every OIDC login writes entries to the workspace audit log:user.oidc.login— on every successful sign-in.user.oidc.provision— additionally, on the very first login. Theelevated_to_adminfield in the detail records whether theinitialAdminEmailrule fired.
user.oidc.* to see SSO activity.
Troubleshooting
| Symptom | Likely cause | Fix | |
|---|---|---|---|
| Sign in with Google button doesn’t appear on the login page | auth.mode isn’t oidc, or clientId / clientSecret is empty | Check the api pod’s env (`kubectl -n definite exec deploy/definite-api — env | grep -E ‘AUTH_MODE|OIDC_‘). Re-run definite upgrade` with the missing values. |
Google rejected the login. Check that the OAuth client_id / client_secret in your values.yaml are correct. | Wrong clientSecret (or it was regenerated in the console after deploy) | Regenerate the client secret in Google Cloud Console and re-apply. | |
state mismatch (CSRF check failed) | Cookie was blocked, or the user took >10 min on Google’s consent screen | Retry. If it persists, check for an aggressive cookie blocker or strict third-party cookie policy. | |
this Google account's domain is not allowed | Personal @gmail.com or wrong workspace | Add the domain to auth.oidc.allowedDomains, or sign in with a matching account. | |
a non-SSO user already exists with the email '...' | A password-mode user owns that address | See Email collisions. | |
redirect_uri_mismatch (shown on Google’s own error page) | The OAuth client’s redirect URI doesn’t match https://<hostname>/api/v1/auth/oidc/callback exactly | Edit the OAuth client in Google Cloud Console and add the exact URI (including scheme and any trailing slash quirks). |
Disabling SSO
Setauth.mode: local (or remove the auth.oidc block) and redeploy. Password login continues to work; the Sign in with Google button disappears.
Existing OIDC-provisioned users are NOT auto-removed — they survive as password-less rows. An admin can delete them via Settings → Members if desired.
