OIDC & OAuth Provider Examples
Ready-made settings for common OIDC and compatible OAuth providers. Configure each provider under Settings > SSO in the organization it should authenticate. Read Authentication & SSO first for the complete login flow and current security limitation.
Everything on this page uses the generic provider type. Only Microsoft Entra ID (entra) and Okta (okta) have dedicated types that derive their endpoints for you.
Before you start
Three things apply to every provider below.
Your redirect URI. Register exactly the value displayed in the provider's Configuration tab. It includes the organization ID and provider slug:
${UIGRAPH_PUBLIC_URL}/api/v1/auth/orgs/<orgID>/callback/<slug>
For organization 01EXAMPLE and provider slug google, register https://uigraph.example.com/api/v1/auth/orgs/01EXAMPLE/callback/google. A different scheme, host, organization ID, slug, or trailing slash can make the provider reject the login.
A UserInfo endpoint and email are mandatory. UIGraph always requests the configured UserInfo endpoint. It merges any ID-token claims with the UserInfo response, with UserInfo taking precedence for duplicate names. The configured Email claim must resolve to a string in that merged result. See ORCID and Facebook for providers that frequently omit email.
Provider slugs are permanent. The slug is part of the callback URL and cannot be changed after provider creation. Choose it before registering the client at the provider.
Scopes and permissions: the short rule
Ask for the least that gets you a verified email, and nothing else.
UIGraph uses the configured email, name, and subject claims and can inspect groups or other returned claims for role mapping. It never writes to the provider and does not store the provider access token; the token is used to request UserInfo and then discarded. Request only identity and authorization claims that UIGraph actually needs.
| You want | Ask for | Don't ask for |
|---|---|---|
| The user's email | The provider's email scope (email, user:email, …) | Anything with write, admin, repo, offline_access |
| A display name on their profile | The provider's basic-profile scope (profile, identify, …) | Full directory or contacts read access |
| Role mapping data | Only the group/role scope required for your selected claim | Broad directory read access |
Dropping the profile scope is safe: if no name claim comes back, UIGraph falls back to using the email address as the display name. That is a legitimate trade if your security team pushes back on profile access.
Two settings do more for your security posture than any scope choice:
- Allowed domains — the email-domain allow-list. On a public provider like Google, GitHub, or Discord, anyone on the internet has an account. Without an allow-list, and with sign-up on, anyone who finds your login page becomes a user. Set this on every public provider.
- Allow sign-up — turn it off for any provider where you can't restrict the domain (Discord and ORCID, in practice). Then only people you have already created in UIGraph can log in, and the provider only proves who they are.
Role assignment is a separate concern. New and existing SSO memberships receive the provider's configured default role unless the first matching claim rule selects another role. See Provisioning, Domains & Roles.
Microsoft Entra ID
Create an application registration in the Microsoft Entra admin center under Identity > Applications > App registrations.
- Add the generated UIGraph callback as a Web redirect URI.
- Create a client secret under Certificates & secrets.
- Copy the application (client) ID, secret value, and directory (tenant) ID.
- Configure token claims or optional claims required by your role mappings.
| Field | Value |
|---|---|
| Provider name | entra |
| Display name | Microsoft |
| Type | entra |
| Directory (Tenant) ID | Your tenant UUID |
| Client ID | Application (client) ID |
| Client Secret | Client secret value |
| Scopes | openid email profile |
| Email / Name / Subject claims | email / name / sub |
UIGraph derives these endpoints from the tenant ID:
https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/authorize
https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
https://graph.microsoft.com/oidc/userinfo
Use a tenant-specific ID instead of common when access should be restricted to one directory. Also set Allowed domains when the returned email domain must be constrained.
Entra group claims may be omitted or represented by an overage indicator when a user belongs to many groups. UIGraph does not follow Microsoft Graph overage links, so test the exact claim returned for users with large memberships before relying on group-based role mapping.
Okta
In the Okta Admin Console, create an OIDC - OpenID Connect application integration with Web Application as the application type.
- Add the generated UIGraph callback under Sign-in redirect URIs.
- Select the authorization-code grant.
- Assign the test users or groups to the application.
- Copy the client ID and client secret.
| Field | Value |
|---|---|
| Provider name | okta |
| Display name | Okta |
| Type | okta |
| Okta Domain | company.okta.com |
| Client ID / Client Secret | Values from the application integration |
| Scopes | openid email profile |
| Email / Name / Subject claims | email / name / sub |
UIGraph derives these organization authorization-server endpoints:
https://<oktaDomain>/oauth2/v1/authorize
https://<oktaDomain>/oauth2/v1/token
https://<oktaDomain>/oauth2/v1/userinfo
Enter only the hostname in Okta Domain, without https:// or a path. If your Okta deployment requires a custom authorization server such as /oauth2/default, use the generic provider type and enter its endpoints explicitly.
Google
Create the client in the Google Cloud Console → APIs & Services → Credentials → Create credentials → OAuth client ID → Web application, and add your redirect URI under Authorized redirect URIs. You also need an OAuth consent screen; for a Workspace-only deployment set its user type to Internal, which limits the client to your own organization.
| Field | Value |
|---|---|
| Provider name | google |
| Display name | Sign in with Google |
| Type | generic |
| Auth URL | https://accounts.google.com/o/oauth2/v2/auth |
| Token URL | https://oauth2.googleapis.com/token |
| Userinfo URL | https://openidconnect.googleapis.com/v1/userinfo |
| Scopes | openid email profile |
| Email / Name claims | email / name |
| Allowed domains | example.com |
Scopes. openid email is the true minimum — profile only adds the display name and picture. These three are the non-sensitive scopes that need no Google verification review. Any Gmail, Drive, or Directory scope pushes your app into Google's verification process and grants access UIGraph has no use for.
Google Workspace tenants also return an hd (hosted domain) claim. Setting Allowed domains to your Workspace domain is the enforcement that matters, since the same client will happily authenticate personal @gmail.com accounts otherwise.
GitHub
Create the app under Settings → Developer settings → OAuth Apps → New OAuth App (personal), or the same path under your organization's settings. Put your redirect URI in Authorization callback URL.
| Field | Value |
|---|---|
| Provider name | github |
| Display name | Sign in with GitHub |
| Type | generic |
| Auth URL | https://github.com/login/oauth/authorize |
| Token URL | https://github.com/login/oauth/access_token |
| Userinfo URL | https://api.github.com/user |
| Scopes | user:email |
| Email / Name claims | email / name |
GitHub isn't an OIDC provider, so UIGraph special-cases it: https://api.github.com/user returns "email": null for users who keep their address private, and UIGraph then calls https://api.github.com/user/emails and uses the primary verified address. That fallback is why the user:email scope is required rather than optional.
Scopes. user:email alone is enough — GitHub returns the public profile from /user for any valid token, so you don't need read:user on top of it. Never grant repo; it is read and write access to every private repository the user can reach, and UIGraph never touches repository contents.
Name claim. GitHub's name is null for users who haven't set a full name, and UIGraph then falls back to the email address. Set the Name claim to login if you would rather see GitHub usernames.
Restricting access. GitHub OAuth apps authenticate any GitHub user, including accounts with no connection to your company. Either set Allowed domains to your verified-email domain, or turn Allow sign-up off and invite users manually. An org-owned OAuth app does not by itself limit who can sign in.
Auth0
In the Auth0 dashboard create an application of type Regular Web Application. Add your redirect URI to Allowed Callback URLs. Under Advanced Settings → Endpoints confirm the token endpoint authentication method is Post (client_secret_post), which is the default for this application type — UIGraph sends the client credentials in the request body, not as HTTP Basic.
Replace YOUR_TENANT.us.auth0.com with your tenant domain (or your custom domain, if configured):
| Field | Value |
|---|---|
| Provider name | auth0 |
| Display name | Sign in with Auth0 |
| Type | generic |
| Auth URL | https://YOUR_TENANT.us.auth0.com/authorize |
| Token URL | https://YOUR_TENANT.us.auth0.com/oauth/token |
| Userinfo URL | https://YOUR_TENANT.us.auth0.com/userinfo |
| Scopes | openid email profile |
| Email / Name claims | email / name |
Scopes. openid email is the minimum; profile adds the display name. Don't add offline_access — that issues a refresh token, and UIGraph discards the token right after reading userinfo, so a refresh token would be a long-lived credential created for nothing.
Permissions. Keep the Management API out of it. Auth0's API permissions (the audience parameter and Management API scopes) are for calling Auth0's own API; UIGraph only needs the OIDC endpoints above.
Auth0 is also the practical way to offer social logins UIGraph can't speak natively: configure them as Auth0 social connections, and UIGraph sees one uniform OIDC provider. This works for any upstream that returns an email address.
OpenID Connect (generic)
Any spec-compliant OIDC provider — Keycloak, Authentik, Zitadel, Ory Hydra, Gitea, PingFederate — works the same way. Fetch the provider's discovery document:
curl -s https://idp.example.com/.well-known/openid-configuration | jq '{authorization_endpoint, token_endpoint, userinfo_endpoint}'
and copy the three endpoints straight into the form. A Keycloak realm, for example, resolves to:
| Field | Value |
|---|---|
| Provider name | keycloak |
| Display name | Sign in with SSO |
| Type | generic |
| Auth URL | https://idp.example.com/realms/<realm>/protocol/openid-connect/auth |
| Token URL | https://idp.example.com/realms/<realm>/protocol/openid-connect/token |
| Userinfo URL | https://idp.example.com/realms/<realm>/protocol/openid-connect/userinfo |
| Scopes | openid email profile |
| Email / Name claims | email / name |
Four requirements on the client you create at the provider:
- Confidential client with a client secret. UIGraph performs a server-side code exchange and always sends
client_secret; a public client configured for PKCE will reject it. - Token endpoint auth method
client_secret_post— credentials in the form body. - A UserInfo endpoint is available. UIGraph calls it for every login.
- The merged claims expose email as a string. Prefer returning the configured email claim from UserInfo. Add an email scope or mapper when necessary.
Scopes. openid email minimum, profile for the display name. Skip provider-specific extras like Keycloak's roles or microprofile-jwt unless you are matching on a claim they add — and if you do map roles, add the one claim that carries group membership (commonly groups) and nothing more.
Facebook
Create an app at developers.facebook.com → Create App → add the Facebook Login product → Settings → Valid OAuth Redirect URIs.
| Field | Value |
|---|---|
| Provider name | facebook |
| Display name | Sign in with Facebook |
| Type | generic |
| Auth URL | https://www.facebook.com/v23.0/dialog/oauth |
| Token URL | https://graph.facebook.com/v23.0/oauth/access_token |
| Userinfo URL | https://graph.facebook.com/v23.0/me?fields=id,name,email |
| Scopes | email |
| Email / Name claims | email / name |
The fields=id,name,email query string on the userinfo URL is required — the Graph API returns only id and name by default, and UIGraph would see no email.
Scopes. email is all you need; public_profile is granted automatically and supplies name. Everything else in Facebook's catalogue (user_friends, pages_*, ads_*) is unrelated to signing in.
Two caveats worth knowing before you commit:
- Facebook omits
emailentirely for accounts registered with a phone number, or where the address is unconfirmed. Those users simply cannot log in, and the failure looks like a generic error. emailneeds Advanced Access through Facebook's App Review before anyone outside your app's own admins, developers, and testers can use it. In development mode it works for your team and stops there.
Because of both, Facebook is a reasonable choice for a consumer-facing deployment and a poor one for an internal tool. Prefer Google or your own OIDC provider for a company login.
Discord
Create an application at discord.com/developers/applications → OAuth2 → Redirects → Add Redirect.
| Field | Value |
|---|---|
| Provider name | discord |
| Display name | Sign in with Discord |
| Type | generic |
| Auth URL | https://discord.com/oauth2/authorize |
| Token URL | https://discord.com/api/oauth2/token |
| Userinfo URL | https://discord.com/api/users/@me |
| Scopes | identify email |
| Email / Name claims | email / username |
| Allow sign-up | Off |
Scopes. identify email is the whole set: identify returns the account (id, username, avatar) and email adds the address. Do not add guilds, guilds.join, connections, or any bot scope — those are for bots and community integrations, and UIGraph is neither.
Name claim. /users/@me returns username (always present) and global_name (the display name, often null). Use username unless you are willing to fall back to the email address.
Restricting access. Discord accounts are personal, so their email domains are effectively random and the Allowed domains list can't do useful work. Turn Allow sign-up off and create users in UIGraph first; Discord then only proves identity. Discord's verified field is not checked by UIGraph, which is a second reason not to leave sign-up open here.
ORCID
Register a public API client at orcid.org → Your account → Developer tools, and add your redirect URI (it must be HTTPS; ORCID rejects http:// redirects, including on localhost). Use sandbox.orcid.org in place of orcid.org throughout to test against ORCID's sandbox.
| Field | Value |
|---|---|
| Provider name | orcid |
| Display name | Sign in with ORCID |
| Type | generic |
| Auth URL | https://orcid.org/oauth/authorize |
| Token URL | https://orcid.org/oauth/token |
| Userinfo URL | https://orcid.org/oauth/userinfo |
| Scopes | openid |
| Email / Name claims | email / name |
| Allow sign-up | Off |
Scopes. openid is both the minimum and, for the public API, essentially the maximum: it gets you the OIDC userinfo response, whose sub is the researcher's ORCID iD. The member-API scopes (/read-limited, /activities/update) grant access to restricted record data and require an ORCID membership — UIGraph has no use for them.
ORCID returns the email claim only when the researcher has set their email visibility to public on their ORCID record, which is not the default. Since UIGraph requires an email, an ORCID account with a private address cannot sign in.
Treat ORCID as a secondary, opt-in provider: tell your users to set at least one email to Everyone in their ORCID privacy settings, keep Allow sign-up off, and offer another login method alongside it.
The sub claim carries the ORCID iD (0000-0002-1825-0097). UIGraph stores that subject as a provider identity link, but the current login flow first matches users by email.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Provider returned no email address | The email scope is missing, the provider hides the address, or the configured claim name does not resolve to a string in the merged claims. |
redirect_uri_mismatch / invalid redirect | The registered URI does not exactly match the generated organization-scoped callback. Check the scheme, host, port, organization ID, provider slug, and trailing slash. |
| Invalid or expired OAuth state | The one-time database state expired after 10 minutes, was already consumed, or was returned to a different organization/provider callback. Restart login from UIGraph. |
token endpoint error "invalid_client" | Wrong client ID/secret, or the provider expects HTTP Basic auth. Set the client's token endpoint auth method to client_secret_post. |
| HTTP 403 from the callback | The user's email domain isn't in Allowed domains, or the account is disabled in UIGraph. |
| First-time users are rejected | Allow sign-up is off. Create the user in UIGraph first, or turn it on with an allow-list in place. |
See also
- Authentication & SSO: supported methods and the complete sign-in flow.
- Provisioning, Domains & Roles: sign-up, account matching, and role mapping.
- SSO Security & Operations: token-validation limits and rollout guidance.
- Environment Variables: URLs:
UIGRAPH_PUBLIC_URL, which every redirect URI is built from. - Operations: running behind TLS, which SSO requires.