OIDC
NomaUBL ships a built-in OIDC single-sign-on integration that lets users authenticate against an external identity provider (Keycloak, Auth0, Azure AD / Microsoft Entra, Okta, Google Workspace…) instead of — or alongside — the local username + password.
The integration uses the standard Authorization Code + PKCE flow, fetches the IdP's metadata from its /.well-known/openid-configuration, and keys NomaUBL users by their email claim.
The login screen's behaviour is driven by the Auth Mode field on the Global template:
| Auth Mode | Login screen |
|---|---|
internal (default) | Local username + password form. |
oidc | Single sign-on button only. |
both | SSO button above the local form — fallback path for break-glass admin access when the IdP is unavailable. |
A default OIDC template is created automatically on fresh installs and upgrades, and can also be created with one click from the + Add OIDC button in the Configuration Manager header.
SSO is a new capability — operators upgrading from a prior version should review the Switching on checklist at the bottom of this page before flipping authMode away from internal.
Opening the editor
- Sidebar → Configuration → System → OIDC.
- The editor is grouped into five sections — Identity provider, Claim mapping, Domain allow-list, Provisioning and Switching on.
At a glance
Identity provider
| Field | Description |
|---|---|
| Issuer URL | Base URL of the OIDC IdP — for example https://idp.example.com/realms/myrealm for a Keycloak realm, an Auth0 tenant URL, or the Azure AD endpoint. NomaUBL fetches the IdP metadata from <issuer>/.well-known/openid-configuration so the individual endpoints (authorise, token, userinfo, JWKS) never need to be entered. |
| Client ID | The OIDC client registered on the IdP side for NomaUBL. |
| Client secret | Optional for public PKCE clients (the IdP can be configured without one). Stored Base64-encoded on disk. |
| Redirect URI | Must exactly match the redirect URI registered on the IdP side. Typical value: https://<your-host>/api/auth/oidc/callback. |
| Scopes | Space-separated. Defaults to openid profile email. Add provider-specific scopes here when extra claims are needed. |
Claim mapping
NomaUBL keys OIDC users by their email — the email claim is matched against the USEMAIL column on F564250. The short USUSER column stays the audit / session key (10-char JDE convention); on auto-provisioning it is derived from the email's local-part.
| Field | Description |
|---|---|
| Email claim | ID-token claim that carries the user's email. Default email — works as-is for Google, Microsoft, Keycloak and Auth0. |
| Full-name claim | Used to populate USFULLNAME on first login and refreshed on every subsequent login. Default name. |
| Username claim (fallback) | Used only when the email claim is missing from the ID token (rare). Most setups leave this blank. |
Domain allow-list
Restricts who can sign in through SSO to a curated set of email tenants. Useful when a corporate IdP also issues tokens to consumer accounts (Gmail being the canonical case).
| Field | Description |
|---|---|
| Allowed email domains | Comma-separated list. Leave blank to allow any verified email. When set, only emails whose domain matches one of these entries can sign in — a personal Google account or a different tenant gets refused at the callback. |
Require Google Workspace domain (hd claim) | Google-only. When set, the ID token must carry an hd claim equal to this value — refuses a personal Gmail that happens to share an address with a Workspace user. Leave blank to skip the check; the field is meaningless for non-Google IdPs. |
Provisioning
Controls what happens when an unknown user signs in successfully against the IdP for the first time.
| Field | Description |
|---|---|
| Auto-create accounts | Y / N. When Y, first sign-in creates the F564250 row with the default role below — the user lands directly on the dashboard. When N, unknown users are refused with a contact admin message even after a successful authentication. |
| Default role | Role assigned to auto-provisioned accounts. Sourced from the actual role list (no hard-coded defaults). Existing accounts keep their current role and are not re-bound on subsequent logins. |
The auto-provisioned username is a short JDE-style 10-character handle derived from the email's local-part — e.g. john.doe@example.com → JOHNDOE. Collisions append a numeric suffix.
OIDC sessions in NomaUBL
Sessions minted through OIDC behave slightly differently from local ones:
- The Profile modal locks the Security tab — password rotation happens at the IdP.
- Identity fields (email, full name) are read-only in the Profile modal — they refresh from the ID token on each sign-in.
- Roles, grants and row filters stay managed in NomaUBL — the IdP only verifies identity. The OIDC user picks up the role assigned to its account on
F564250, exactly like a local user. - Sign-out invalidates the local NomaUBL session; it does not call the IdP's
end_session_endpointby default.
Switching on
Once the OIDC template is filled, the Auth Mode field on the Global template controls how the login screen behaves:
| Mode | Result |
|---|---|
internal (default) | Local form only. OIDC is configured but not exposed. |
oidc | SSO button only. Local form hidden. |
both | SSO button above the local form — recommended during a rollout so admin accounts retain a fallback path. |
A safe rollout typically goes:
- Fill the OIDC template and save.
- Set Auth Mode to
both. Sign in with an SSO test account end-to-end. - Confirm the auto-provisioned
F564250row has the expected role andUSEMAIL. - Flip Auth Mode to
oidconce every account has signed in at least once (or once every account has the right role assigned manually if auto-provisioning isN).
When Auth Mode is oidc, the local form is hidden — there is no break-glass path if the IdP is unreachable. Keep at least one local admin account on F564250 and leave Auth Mode at both if the operational risk of an IdP outage is unacceptable.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Sign-in refused at callback with a domain message. | The user's email domain is not in Allowed email domains, or the Google hd claim does not match the required value. |
| Sign-in refused with "user not found" | Auto-create accounts is N and the user has no pre-existing F564250 row — provision the user manually, or flip auto-create on. |
| Login loops back to the IdP screen. | The Redirect URI in NomaUBL does not exactly match the one registered on the IdP side (trailing slash, scheme, hostname). |
| 401 / metadata fetch error on startup. | The Issuer URL is wrong, unreachable from the NomaUBL host, or its /.well-known/openid-configuration is gated behind authentication. |
| Operator can sign in but lands on an empty dashboard. | The default role assigned at provisioning has no page grants. Bind the account to a fuller role in Configuration → Security → Users. |
Tips & best practices
- Use
bothduring rollout. It keeps the local form alive as a fallback while the SSO is being shaken down. Flip tooidconly when every account is verified to work through the IdP. - Keep
Allowed email domainspopulated when the IdP can issue tokens to consumer accounts (Google Workspace, Microsoft Entra with B2B). It is cheap to set and removes a category of mistake. - Auto-provisioning saves operator time — but only when paired with a deliberately low-privilege default role. Pick
viewer(or a custom new-user role) so newly-created accounts can be reviewed before they get richer permissions. - The OIDC user's permissions live in NomaUBL. Even with SSO on, granting a user access to a page is still a NomaUBL action — the IdP only attests identity.