Skip to main content

OpenID Connect (OIDC)

Anaphora supports login through OAuth 2.0 / OpenID Connect providers. OIDC is simpler to set up than SAML and has similar enterprise features.

OpenID Connect authentication settings in Anaphora

Overview​

OIDC is built on OAuth 2.0 and has fewer settings than SAML. Anaphora discovers the provider configuration automatically through the well-known endpoint. Sessions are token-based, with secure, stateless authentication.

Supported providers​

ProviderIssuer URLNotes
Googlehttps://accounts.google.comGoogle Workspace or personal
Auth0https://your-tenant.auth0.comFull-featured IdP
Keycloakhttps://keycloak.company.com/realms/your-realmSelf-hosted option
Oktahttps://your-org.okta.comEnterprise IdP
Azure ADhttps://login.microsoftonline.com/{tenant}/v2.0Microsoft cloud
OneLoginhttps://your-domain.onelogin.com/oidc/2Enterprise SSO
Ping Identityhttps://auth.pingone.com/{env-id}/asEnterprise
CustomAny OIDC-compliant issuerMust support discovery

Configuration​

Step 1: Create an OAuth application​

Create an OAuth/OIDC application in your identity provider.

Google​

  1. Go to Google Cloud Console
  2. APIs & Services > Credentials > Create Credentials > OAuth Client ID
  3. Application type: Web application
  4. Authorized redirect URIs: https://anaphora.company.com/auth/login-oidc/callback
  5. Copy Client ID and Client Secret

Auth0​

  1. Applications > Create Application
  2. Choose "Regular Web Application"
  3. Settings tab:
    • Allowed Callback URLs: https://anaphora.company.com/auth/login-oidc/callback
    • Allowed Logout URLs: https://anaphora.company.com/auth/login
  4. Copy Domain, Client ID, and Client Secret

Keycloak​

  1. Clients > Create Client
  2. Client ID: anaphora
  3. Client Protocol: openid-connect
  4. Access Type: confidential
  5. Valid Redirect URIs: https://anaphora.company.com/auth/login-oidc/callback
  6. Backchannel logout URL: https://anaphora.company.com/auth/logout-oidc/backchannel, with Backchannel logout session required on (optional, see Logout)
  7. Copy Client Secret from Credentials tab

Okta​

  1. Applications > Create App Integration
  2. Sign-in method: OIDC
  3. Application type: Web Application
  4. Sign-in redirect URIs: https://anaphora.company.com/auth/login-oidc/callback
  5. Copy Client ID and Client Secret

Azure AD​

  1. App registrations > New registration
  2. Redirect URI: Web > https://anaphora.company.com/auth/login-oidc/callback
  3. Certificates & secrets > New client secret
  4. Copy Application (client) ID and secret value

Step 2: Configure Anaphora​

  1. Go to Settings > System > Auth > OIDC
  2. Enter the configuration:
FieldDescriptionExample
IssuerURL of the provider. Other paths are relative to it. Requiredhttps://accounts.google.com
Callback URLFull callback URL. Empty uses the default (see below)https://anaphora.company.com/auth/login-oidc/callback
Logout pathPath of the provider logout endpoint. With the default, Anaphora uses the end_session_endpoint that the provider publishes (see Logout). Default: /protocol/openid-connect/logout/protocol/openid-connect/logout
Client IDOAuth client identifier. Requiredabc123def456
Client secretOAuth client secret (stored encrypted). Required
ScopeRequested scopes. Default: openid, profile, emailopenid email profile
Username parameterClaim for the username. Default: preferred_usernamepreferred_username
Groups parameterClaim for the groups/roles. Default: groupsgroups
System groupsGroups whose users get the system role (see System groups)/anaphora-admins
Proxy URLProxy for the requests to the providerhttp://proxy.company.com:3128
Tls insecure skip verifyTurns off the check of the TLS certificate of the provider. Not recommended (see The TLS certificate of the issuer)
Tls CA certCA certificate (PEM) of the provider or the proxy, trusted next to the public CAs
Proxy tls insecure skip verifyTurns off the check of the TLS certificate of an HTTPS proxy. Only this setting does that
Clock tolerance secondsClock difference with the provider, in seconds, that the ID token and the logout token can have. Default: 030
Auth methodToken endpoint auth method (see below)client_secret_basic
User info sourceSource of the user profile (see below)user_info_endpoint
Extra configYAML object with more options (see below)
  1. Click Save
  2. To activate OIDC, add oidc to Strategies in Settings > System > General
Settings from the environment

You can also set OIDC with environment variables. Then the environment owns the OIDC settings, and the settings page cannot change them. See Configure from the environment.

Callback URL​

The IdP redirects users to the Callback URL after authentication.

Default: https://<anaphora-external-url>/auth/login-oidc/callback

Add this URL to the allowed redirect URIs of your IdP:

ProviderSetting location
GoogleAuthorized redirect URIs
Auth0Allowed Callback URLs
KeycloakClient Settings > Valid Redirect URIs
OktaSign-in redirect URIs
Azure ADRedirect URIs
Keycloak

In Keycloak, go to Clients > your client > Settings > Valid Redirect URIs and add the callback URL.

Step 3: Configure scopes​

Set the Scope field to the scopes you need.

Default: openid, profile, email

ScopeData returned
openidRequired for OIDC
emailUser email address
profileName, picture, etc.
groupsGroup memberships (provider-specific)
Custom scopes

Be careful with custom scopes. A scope that does not exist can cause authentication errors, such as redirect loops back to the login URL after authorization.

Configure from the environment​

Instead of the settings page, you can configure OIDC with environment variables. This is an Enterprise feature.

VariableRequiredDefaultDescription
OIDC_ISSUERYesThe issuer URL, as the browser reaches it
OIDC_CLIENT_IDYesThe client ID
OIDC_CLIENT_SECRETYesThe client secret
OIDC_INTERNAL_ISSUERNoThe issuer URL as the Anaphora container reaches it, when the two are not the same
OIDC_SCOPESNoopenid profile emailThe scopes to request, separated by spaces
OIDC_USERNAME_CLAIMNopreferred_usernameThe claim that names the user
OIDC_GROUPS_CLAIMNogroupsThe claim that lists the user's roles
OIDC_TLS_CA_CERTNoA CA certificate (PEM) to trust next to the public CAs, for the TLS certificate of the issuer
OIDC_TLS_INSECURE_SKIP_VERIFYNofalsetrue turns off the check of the TLS certificate of the issuer
OIDC_CLOCK_TOLERANCE_SECONDSNo0The clock difference with the provider, in seconds, that the ID and logout tokens can have
OIDC_SYSTEM_GROUPSNoGroups, separated by commas. A user in one of them gets the system role (the Settings menu)
  • The three required variables switch OIDC on. A partial set logs a warning and leaves OIDC off.
  • A value that is not valid also leaves OIDC off: a CA that does not parse or that holds more than complete certificates, a switch that is not true or false (1 or 0), or a tolerance that is not a whole number of seconds. OIDC is then off, also when Authfish keeps an older copy of these settings in its database.
  • An optional variable without the three required ones changes nothing, and the start log names it.
  • The identity provider must allow the callback <PUBLIC_URL>/auth/login-oidc/callback.
  • The identity provider must send the user's roles (admin, user, superuser) in the claim that OIDC_GROUPS_CLAIM names.
  • The environment owns these settings. The settings page cannot change them, and Anaphora does not save them in its database.
  • A new installation starts with OIDC in its list of sign-in methods. On an existing installation, switch OIDC on under Settings, in the list of sign-in methods.
  • Anaphora reads the variables at every start.

The other settings use fixed values: client_secret_basic as auth method and the userInfo endpoint as user info source. The logout goes to the logout endpoint that the provider publishes. With OIDC_INTERNAL_ISSUER, it goes to <OIDC_ISSUER>/protocol/openid-connect/logout, the Keycloak form.

System role from the environment​

OIDC_SYSTEM_GROUPS lists the groups whose users get the system role, as the groups claim names them, for example OIDC_SYSTEM_GROUPS=admin. Use a name that is unique at the provider: a Keycloak realm role, or the full path of a group (/admins), because group names can repeat under different parents. Names match whole and with case. When the variable is not set, no OIDC user gets the system role. See System groups.

The TLS certificate of the issuer​

Anaphora checks the TLS certificate of an https issuer. The certificate must chain to a public CA or to OIDC_TLS_CA_CERT. It must also name the address in the issuer URL: for an IP address, an IP address entry in its subjectAltName. The issuer URL here is OIDC_INTERNAL_ISSUER when it is set, else OIDC_ISSUER.

OIDC_TLS_CA_CERT takes the text of the PEM file, with its line breaks, or on one line with \n in place of each line break. A bundle of more than one certificate is accepted, and the OpenSSL TRUSTED CERTIFICATE form too. A private key in the text is refused.

OIDC_TLS_INSECURE_SKIP_VERIFY=true turns the check off, the name check included. The connection to the issuer is then not protected, so use it only for a test. When both are set, the CA wins: the check stays on, and the start log says that the switch is ignored. The start log line [oidc] issuer ... names each of these settings that is on.

Upgrade from 0.16 or older

From 0.17.0, an https issuer URL on an IPv4 address, on localhost, on a *.localhost name or on [::1] needs one of these:

  • The certificate names that address and chains to a public CA: no action.
  • The certificate names that address: set OIDC_TLS_CA_CERT to its CA. This is the preferred fix.
  • The certificate names a host name only: put that host name in the issuer URL and set OIDC_TLS_CA_CERT, or set OIDC_TLS_INSECURE_SKIP_VERIFY=true.

Without one of them, OIDC sign-in stops, and local users can still sign in. The start log says OIDC issuer discovery failed: and the reason: self-signed certificate, unable to verify the first certificate (a private CA) or Hostname/IP does not match certificate's altnames. The upgrade script shows that line when the upgrade is done.

OIDC that you set up in the settings page needs no action: the upgrade turns on Tls insecure skip verify where the old rule skipped the check, and the start log warns about it. Set Tls CA cert instead.

Keycloak in the same Docker network

When the browser reaches Keycloak at a public URL and the Anaphora container reaches it at an internal URL, set OIDC_ISSUER to the public URL and OIDC_INTERNAL_ISSUER to the internal one, for example http://keycloak:8080/realms/your-realm. Anaphora uses the internal URL for discovery and for the calls from the server. Keycloak must publish the browser endpoints under the public URL (KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true).

Claim mapping​

Map OIDC claims to the Anaphora user fields.

Standard claims​

Anaphora fieldOIDC claimDescription
Usernamepreferred_username (set in Username parameter)Unique identifier
EmailemailUser email
Display namenameFull name

Group claims​

The group claim name is different for each provider:

ProviderGroups claim
Googlegroups (requires Workspace)
Auth0https://your-app/roles (custom)
Keycloakgroups or realm_access.roles
Oktagroups
Azure ADgroups

Custom claim mapping​

  1. Go to Settings > System > Auth > OIDC
  2. Set the claim names:
Username parameter: preferred_username
Groups parameter: groups

Group-based roles​

Map IdP groups to Anaphora roles.

Groups parameter​

The Groups parameter is the claim that contains the group or role information. Default: groups. The claim is a list of groups, or one string for one group.

Important: Add Roles to ID Token

You must configure your IdP to include roles/groups in the ID token.

In Keycloak:

  1. Go to Client Scopes > profile
  2. Select Mappers > Add mapper > From predefined...
  3. Add the groups mapping

Role mapping​

Each IdP group becomes an Anaphora role with the same name.

  1. Go to Settings > System > Permissions
  2. In a space, add a permission for the role, and set its access:
IdP group/roleAccess
anaphora-adminsAdmin
anaphora-editorsRead Write
anaphora-viewersRead Only

System role​

A user in one of the System groups gets the system role: the Settings menu and Admin access to every space. See System groups.

Auth0 roles example​

In Auth0, use Rules or Actions to add roles to tokens:

// Auth0 Action
exports.onExecutePostLogin = async (event, api) => {
const roles = event.authorization?.roles || [];
api.idToken.setCustomClaim('roles', roles);
};

Then, in Anaphora:

  • Set Groups parameter to roles
  • In Settings > System > Permissions, give admin the Admin access and editor the Read Write access

Advanced settings​

Auth method​

The Auth method sets how Anaphora sends the credentials to the token endpoint.

Default: client_secret_basic

MethodDescription
client_secret_basicSends the client ID and secret in the Authorization header (URL-encoded). The standard method for most providers.
client_secret_postSends the client ID and secret in the request body (not encoded). Use it when your provider cannot decode encoded values (for example, LemonLDAP).

User info source​

The User info source sets where Anaphora gets the user profile information.

Default: user_info_endpoint

SourceDescription
user_info_endpointMakes one more call to the userInfo endpoint to get the latest profile data.
access_tokenReads the profile information from the access token.
id_tokenReads the profile information from the ID token.

Extra configuration​

The Extra config field accepts a YAML object with two optional sections:

SectionDescription
issuerAdditionalParametersChange the OIDC issuer discovery
clientAdditionalParametersChange the OIDC client configuration
issuerAdditionalParameters:
metadata:
jwks_uri: https://example.com/.well-known/jwks.json

clientAdditionalParameters:
metadata:
default_max_age: 0

For the available options, see:

caution

Use extra configuration options with caution. Incorrect settings may break OIDC authentication.

Session settings​

SettingWhereDescription
Max age hoursSettings > System > BackendHow long an Anaphora session lasts. Default: 60
Logout pathSettings > System > Auth > OIDCLogout from the IdP when you log out of Anaphora

For Keycloak, also add https://<anaphora-external-url>/auth/login to Valid post logout redirect URIs.

Logout​

When a user logs out of Anaphora, Anaphora ends the session, then sends the browser to the end_session_endpoint that the provider publishes, with client_id, post_logout_redirect_uri and id_token_hint. A Logout path that you set to another value wins. A provider without a logout endpoint (Google) ends the session in Anaphora only.

A logout at the provider (in another application of the realm, by an admin, or on the account page) can end the Anaphora session too. Set the back-channel logout URL of the client to:

<PUBLIC_URL>/auth/logout-oidc/backchannel

In Keycloak, this is Backchannel logout URL, with Backchannel logout session required on. The logout token must be signed by the issuer for this client and be at most 5 minutes old, and each token works once. It ends every session with its sid (or, without one, its sub), in every browser.

Discovery settings​

Anaphora reads the provider endpoints from <Issuer>/.well-known/openid-configuration. There are no separate fields for them. To change an endpoint, for example jwks_uri, use issuerAdditionalParameters.metadata in Extra config.

Testing​

Test OIDC configuration​

  1. Log out, then click Continue with OIDC on the login page
  2. Anaphora sends you to your IdP
  3. Log in with IdP credentials
  4. Make sure that the IdP sends you back to Anaphora
  5. Make sure that the user gets the correct spaces

Debug mode​

At each OIDC login, the Anaphora log shows the user profile at the info log level:

  1. Make sure that Log level in Settings > System > General is info, debug or trace
  2. Try to log in
  3. Find the line OIDC login from ... in the Anaphora log
  4. Make sure that the groups/roles are present

Troubleshooting​

IssueSolution
Invalid redirect URIMake sure that the callback URL is the same in both systems
Invalid clientCheck the Client ID and Secret
Discovery failedCheck Issuer, make sure that /.well-known/openid-configuration is accessible
Groups not receivedCheck Scope, Groups parameter and the IdP configuration
Token expired, or not yet validCheck clock synchronization (NTP), or set Clock tolerance seconds
OIDC issuer discovery failed: in the logSee The TLS certificate of the issuer
User has no usernameCheck Username parameter. A profile without that claim is refused

When the sign-in at the provider fails (for example an expired login page), the browser goes back to the Anaphora login page, which shows the reason.

Common errors​

"invalid_client"

  • The Client ID or Secret is incorrect
  • The Client Secret can be expired (make a new one)

"redirect_uri_mismatch"

  • The Callback URL in Anaphora is not the same as in the IdP configuration
  • Check for trailing slashes, and for http instead of https

"invalid_scope"

  • The IdP does not allow a requested scope
  • Remove the unsupported scopes

Provider-specific notes​

Google Workspace​

To get group memberships:

  1. Enable the Directory API in Google Cloud Console
  2. Configure domain-wide delegation
  3. Add the https://www.googleapis.com/auth/admin.directory.group.readonly scope

Azure AD​

For group claims:

  1. App registration > Token configuration > Add groups claim
  2. Choose "Groups assigned to the application" for large directories

Keycloak​

Keycloak includes groups by default. Configure client mappers for custom claims.

Best practices​

  • Use HTTPS for all endpoints
  • Store Client Secret securely (Anaphora encrypts it)
  • Request only the scopes you need
  • Map groups to roles for scalable access management
  • Monitor token expiration and refresh behavior

Next steps​

  • SAML: SAML 2.0 SSO, an alternative to OIDC
  • Spaces: configure space-based access