-
Notifications
You must be signed in to change notification settings - Fork 0
OIDC Single Sign On
JustGate supports OIDC-based single sign-on on top of (or instead of) local accounts.
| Method | When it takes effect | Suitable for |
|---|---|---|
Setup wizard (/setup) |
Immediately on first run | Initial bootstrap |
| Admin UI (Settings → OIDC) | Immediately (stored in DB) | Runtime changes, secret rotation |
| Helm values / env vars | On pod start (static) | GitOps, CI/CD pipelines |
The Admin UI (DB) configuration takes precedence over env vars when an enabled OIDC record is stored in the database.
When configuring OIDC via the Admin UI, make sure the SSO active toggle is on before saving. The sign-in page only shows the SSO button when the stored config has enabled = true. The toggle auto-activates as soon as you fill in all three required fields (issuer, client ID, client secret).
JustGate uses OIDC Discovery to configure next-auth automatically. On startup it fetches:
GET <issuer>/.well-known/openid-configuration
The response must return HTTP 200 with a valid JSON document. If the pod receives anything else — 503, 404, connection refused, TLS error — the sign-in flow will fail immediately with SIGNIN_OAUTH_ERROR.
The issuer URL is the most common source of errors. It must match exactly what the identity provider publishes in the discovery document.
| Provider | Issuer URL pattern |
|---|---|
| Keycloak | https://<host>/realms/<realm-name> |
| Keycloak (legacy < 17) | https://<host>/auth/realms/<realm-name> |
| Dex | https://<host>/dex |
| Auth0 | https://<tenant>.eu.auth0.com |
| Azure AD | https://login.microsoftonline.com/<tenant-id>/v2.0 |
https://accounts.google.com |
|
| Authentik | https://<host>/application/o/<app-slug>/ |
| GitLab | https://gitlab.com |
Keycloak example: if your realm is called
myrealm, the issuer is
https://keycloak.example.com/realms/myrealm
Verify by opening that URL in a browser — you should see a JSON document with anissuerfield.
The error expected 200 OK, got: 503 Service Unavailable means next-auth reached the server but received a failure response while fetching the discovery document.
1. Wrong realm / path
The URL resolves but the realm doesn't exist or the path is wrong.
curl -v https://<issuer>/.well-known/openid-configuration2. Provider temporarily unavailable
The IdP is overloaded or still starting. Wait and retry.
3. Pod cannot reach the IdP
If the IdP is on an internal network, DNS may resolve but routing rules or Kubernetes NetworkPolicies may block traffic.
kubectl exec -it <justgate-pod> -- \
wget -qO- https://<issuer>/.well-known/openid-configuration4. Internal / self-signed CA
The discovery request fails TLS verification (shows as unable to get local issuer certificate). Fix: configure customCAs in Helm — see Internal CA / Self-Signed Certificates.
5. Trailing slash mismatch
JustGate strips a trailing slash from the issuer automatically. If you still see issues, ensure your IdP and the issuer value you supply have the same format (both with or both without a trailing slash).
Set the OIDC values in values.yaml:
frontend:
nextauthUrl: "https://justgate.example.com"
oidc:
issuer: "https://keycloak.example.com/realms/myrealm"
clientId: "justgate"
clientSecret: "your-client-secret"
name: "Login with Keycloak" # optional button labelOr pass with --set flags:
helm upgrade justgate oci://ghcr.io/justlabv1/justgate \
--set frontend.nextauthUrl=https://justgate.example.com \
--set frontend.oidc.issuer=https://keycloak.example.com/realms/myrealm \
--set frontend.oidc.clientId=justgate \
--set frontend.oidc.clientSecret=<secret>The
clientIdandclientSecretare written into a KubernetesSecretautomatically by the chart. You do not need to create it manually.
Or as environment variables on the frontend container:
JUST_GATE_OIDC_ISSUER=https://keycloak.example.com/realms/myrealm
JUST_GATE_OIDC_CLIENT_ID=justgate
JUST_GATE_OIDC_CLIENT_SECRET=<secret>
JUST_GATE_OIDC_NAME="Login with Keycloak"- Sign in as an admin and navigate to Settings → OIDC.
- Fill in the fields:
| Field | Description |
|---|---|
| Issuer URL | Full issuer URL including realm (see table above). No trailing slash. |
| Client ID | The client/application ID registered in your IdP. |
| Client Secret | The client secret. Leave blank to keep the existing stored value. |
| Button Label | Text shown on the sign-in page (default: Single Sign-On). |
| Groups Claim | JWT claim containing groups/roles for org mapping (e.g. groups or realm_access.roles). Optional. |
- The SSO active toggle (at the bottom of the form) must be on for the sign-in button to appear. It activates automatically once the issuer, client ID, and client secret are all filled in — you rarely need to touch it manually.
- Click Save. Changes take effect on the next sign-in request — no restart needed.
The client secret is AES-256-GCM encrypted before being written to the database.
In Keycloak, create a new client for JustGate:
| Setting | Value |
|---|---|
| Client type | OpenID Connect |
| Client ID |
justgate (or whatever you set as clientId) |
| Client authentication |
On (confidential client) |
| Valid redirect URIs | https://justgate.example.com/api/auth/callback/oidc |
| Web origins | https://justgate.example.com |
Retrieve the client secret from the Credentials tab.
If you want to use OIDC Org Mappings, add a mapper to include groups in the ID token:
- Open the client in Keycloak → Client scopes →
justgate-dedicated(or the default scope). - Add a Group Membership mapper.
- Set Token Claim Name to
groups. - Enable Add to ID token.
If your IdP uses a certificate signed by an internal CA, mount the CA bundle via Helm:
customCAs:
enabled: true
certificates: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW+gAwIBAgIJA...
-----END CERTIFICATE-----customCAs:
enabled: true
existingConfigMap: my-ca-bundle # must have a 'ca-bundle.crt' keyThe chart automatically sets NODE_EXTRA_CA_CERTS for the Next.js process so that discovery requests and token exchange use the custom CA.
JustGate can automatically assign users to organisations based on OIDC groups or roles:
- Ensure your IdP includes a groups/roles claim in the ID token (see Keycloak Client Configuration above).
- In Settings → OIDC, set the Groups Claim field to the name of that claim (e.g.
groups,realm_access.roles). - Navigate to Settings → OIDC → Org Mappings and map OIDC group names to JustGate organisation names.
When a user signs in via OIDC, JustGate reads the groups claim from the ID token and automatically adds the user to mapped organisations. If the user's groups change in the IdP, the membership is updated on the next sign-in.
| OIDC Group | JustGate Organisation |
|---|---|
platform-team |
platform |
ops-eu |
operations-eu |
ops-us |
operations-us |
To run OIDC-only (no email/password login):
# Env var
JUST_GATE_LOCAL_ACCOUNTS_ENABLED=false# Helm values.yaml
frontend:
localAccountsEnabled: falseWhen localAccountsEnabled is false, the email/password form is hidden from the sign-in page and the local registration endpoint is disabled.