Single Sign-On (OAuth2/OIDC)

The CIB seven webclient supports Single Sign-On with any identity provider that implements OpenID Connect (OIDC), for example Microsoft Entra ID (Azure AD) or Keycloak. When SSO is active, the login page redirects the user to the identity provider, and after a successful login the user is redirected back to the webclient.

Webclient SSO is a feature of the webclient itself and does not require Spring Security. It works the same way on all distributions: CIB seven Run, Tomcat and WildFly. Also, it can be enabled for Spring Boot applications without Spring Security.

Activation

To activate SSO, select the OAuth2UserProvider as user provider and set cibseven.webclient.sso.active to true:

cibseven:
  webclient:
    user:
      provider: org.cibseven.webapp.auth.OAuth2UserProvider
    authentication:
      jwtSecret: <jwtSecret>
    sso:
      active: true
      endpoints:
        authorization: <authorizationUri>
        token: <tokenUri>
        jwks: <jwksUri>
        user: <userInfoUri>
      clientId: <clientId>
      clientSecret: <clientSecret>
      scopes: openid email profile
      userIdProperty: preferred_username
      userNameProperty: name
  • scopes is the list of scopes (separated by spaces) that the webclient requests from the identity provider. You can configure it freely, for example to add offline_access or a custom API scope.
  • userIdProperty and userNameProperty are the claims of the ID token that are used as CIB seven user ID and display name.
  • authentication.jwtSecret is always required: the webclient uses it to sign the session token exchanged between the browser and the webclient.
    • With sso.accessTokenToEngineRest: false (default), the webclient also sends this token to the engine REST API, which validates it with JWT authentication. In that case, the engine must be configured with the same secret.
    • With sso.accessTokenToEngineRest: true, the webclient sends the access token from the identity provider to the engine instead. The secret is then only used for the webclient session. This requires an engine REST API secured with OAuth2.

All available properties are listed in the cibseven.webclient.sso property reference.

Redirect URI

Register the following redirect URI for the client at your identity provider:

<scheme>://<host>:<port>/<webclient path>/sso-login.html

For example, https://cibseven.example.com/webapp/sso-login.html. The path /webapp is the default value of camunda.bpm.webapp.applicationPath, so adjust it if you deploy the webclient under another path.

Redirect URI must match the browser URL

The webclient builds the redirect URI from the URL in the browser, so the registered URI must match exactly the URL users open (scheme, host name, port and path), including when the webclient runs behind a reverse proxy.

In Microsoft Entra ID, register the redirect URI under the platform type Web, because the webclient exchanges the login code on the server with the client secret or client assertion.

Where to Configure the Properties

The cibseven.webclient.* properties can be set in the following places, depending on the distribution:

Distribution Where to configure
CIB seven Run The configuration file configuration/default.yml or configuration/production.yml.
Spring Boot The application.yaml (or application.properties) of your application.
Tomcat You can place a cibseven-webclient.yaml file in the $CATALINA_HOME/lib folder. Alternatively, properties can be added to cibseven-webclient.properties, which is automatically generated the first time by start-cibseven.bat/start-cibseven.sh.
You can also pass the properties as -D options, for example in CATALINA_OPTS in bin/setenv.sh / bin/setenv.bat, or as environment variables (for example CIBSEVEN_WEBCLIENT_SSO_ACTIVE=true).
WildFly You can define system properties in the standalone.xml.
Alternatively, properties can be added to cibseven-webclient.properties, which is automatically generated the first time by start-cibseven.bat/start-cibseven.sh for JWT mechanism purposes and placed in $JBOSS_HOME/modules/org/cibseven/config/main/.

No need to change the WAR file

The webclient imports the optional files cibseven-webclient.properties and cibseven-webclient.yaml from the classpath, so you do not need to modify the application.yaml inside the WAR file.

Example for cibseven-webclient.properties:

cibseven.webclient.user.provider=org.cibseven.webapp.auth.OAuth2UserProvider
cibseven.webclient.sso.active=true
cibseven.webclient.sso.endpoints.authorization=<authorizationUri>
cibseven.webclient.sso.endpoints.token=<tokenUri>
cibseven.webclient.sso.endpoints.jwks=<jwksUri>
cibseven.webclient.sso.endpoints.user=<userInfoUri>
cibseven.webclient.sso.clientId=<clientId>
cibseven.webclient.sso.clientSecret=<clientSecret>
cibseven.webclient.sso.scopes=openid email profile
cibseven.webclient.sso.userIdProperty=preferred_username
cibseven.webclient.sso.userNameProperty=name

Users, Groups and Authorizations

After the login, the value of the userIdProperty claim becomes the CIB seven user ID. The webclient uses this ID to call the engine, and the engine applies groups, tenants and authorizations for this user ID.

By default, the engine resolves the groups and tenants of the user from its configured identity service: the CIB seven database or LDAP. Therefore, a user with the same user ID must exist there, with the required group memberships and authorizations.

Choose a userIdProperty whose value matches the user IDs in your identity service, for example preferred_username or a custom claim. If userIdProperty is empty or wrong, the login will fail.

Granting Initial Administrator Permissions

To grant initial administrator permissions to an SSO user or group, use the Administrator Authorization Plugin. If you run a Spring Boot application or the CIB seven Run distro, you can also use the camunda.bpm.admin-user property. The ID you use must match the value of the userIdProperty claim, otherwise the permissions do not apply to the SSO user.

When Spring Security Is Required

Use case Spring Security required
SSO login to the webclient (OAuth2UserProvider, cibseven.webclient.sso.*) No. Works on all distributions.
Secure the engine REST API with OAuth2 (resource server), together with cibseven.webclient.sso.accessTokenToEngineRest=true Yes, cibseven-bpm-spring-boot-starter-security
Read the groups of the user from the token instead of the CIB seven database or LDAP (OAuth2IdentityProvider) Yes, cibseven-bpm-spring-boot-starter-security

The cibseven-bpm-spring-boot-starter-security is available for Spring Boot and CIB seven Run. See Spring Security OAuth2 Integration for these scenarios.

Assertion-based Authentication

A secretless client authentication approach can be configured so that no client secret is used or transmitted during the authentication process. The following authentication methods are supported:

  • JWT Bearer Client Assertion: The client authenticates using a signed JWT. A PEM-encoded private key must be configured as the keyLocation to sign the client assertion.
  • Azure Workload Identity: The client authenticates using Azure Workload Identity without requiring a client secret or certificate.

The CIB seven webclient can be configured to use assertion-based authentication by setting its cibseven.webclient.sso.assertion properties.

For more information about assertion-based authentication, refer to RFC 7521.

Microsoft Entra ID

Microsoft Entra ID provides the endpoints of a tenant at https://login.microsoftonline.com/<tenantId>/v2.0/.well-known/openid-configuration. Use the v2.0 endpoints.

App registration checklist

  1. Redirect URI: register the redirect URI with the platform type Web, not Single-page application. The webclient redeems the login code on the server with a client secret or client assertion, which Entra ID does not allow for a Single-page application redirect URI.
  2. Expose an API and define a scope: set the Application ID URI to api://<clientId> and define a custom scope, for example cibseven.
  3. API permissions: in the API permissions section, select Add a permission, find your app registration among the APIs my organization uses, select it and choose Delegated permissions to add the custom scope.
    • If you defined the scope with Admins only consent, grant admin consent.
  4. Client secret: create a client secret. Alternatively, you can use a client assertion.

Configuration for Entra ID

cibseven:
  webclient:
    user:
      provider: org.cibseven.webapp.auth.OAuth2UserProvider
    sso:
      active: true
      endpoints:
        authorization: https://login.microsoftonline.com/<tenantId>/oauth2/v2.0/authorize
        token: https://login.microsoftonline.com/<tenantId>/oauth2/v2.0/token
        jwks: https://login.microsoftonline.com/<tenantId>/discovery/v2.0/keys
        user: https://graph.microsoft.com/oidc/userinfo
      clientId: <Application (client) ID>
      clientSecret: <secret>
      scopes: openid profile email offline_access api://<clientId>/cibseven
      userIdProperty: preferred_username
      userNameProperty: name
  • The custom scope api://<clientId>/<customScope> is mandatory. Without it, Entra ID issues a Microsoft Graph access token. The webclient validates the signature of the access token, and third parties cannot validate Graph tokens. The user then sees a certificate or signature validation error after the login.
    • If you defined a custom Application ID URI (different than the recommended one), notice that the custom scope must match it, like <applicationIdUri>/<customScope>.
  • userIdProperty and userNameProperty are read from the ID token on the browser login. With the scope profile, a v2.0 ID token contains preferred_username (usually the user principal name, UPN) and name.
  • The user ID must match the user IDs in your identity service. If your LDAP user IDs are, for example, sAMAccountName, then preferred_username (user@domain) does not match. You can provide a matching claim in Entra ID (token configuration or claims mapping), or create the users with their UPN. Alternatives are email (can be empty) and oid (a stable GUID, but not human-readable).
  • endpoints.user is mandatory. It has no default value, and the application does not start without it.
  • offline_access scope is mandatory (for OAuth2). Without it, Entra ID issues no refresh token.

Refresh Tokens

The OAuth2UserProvider does not support rolling refresh tokens (refresh tokens that are invalidated once they have been used). Take this into account when you configure the token policies of your identity provider.

Entra ID Troubleshooting

If you checked the generic troubleshooting and did not find the cause of your login failure, the following problems are specific to Microsoft Entra ID. To investigate further, open the developer tools (F12) before you log in: the login page sso-login.html stops at a breakpoint, and you can inspect the URL and the response of the login request. Entra ID reports its errors in the URL.

SignatureException

A pop-up shows a SignatureException. The login request returns HTTP 500, and the backend log contains:

io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

Cause: the custom scope is missing in sso.scopes. Entra ID then issues a Microsoft Graph access token, which the webclient cannot validate. Add the custom scope api://<clientId>/<customScope>, see the example configuration.

AuthenticationException

A pop-up shows an AuthenticationException. The login request returns HTTP 401.

Cause: resource not found. The login stops at the breakpoint, and the URL contains an error from Entra ID:

<scheme>://<host>:<port>/webapp/sso-login.html#error=invalid_resource&error_description=AADSTS500011: The resource principal named api://<clientId> was not found in the tenant named <tenantId>. ...

The login request then returns HTTP 401 with AADSTS900144: The request body must contain the following parameter: 'code'. This second error is a consequence of the first: the browser came back without a code. Nothing is written to the backend log. Check the Application ID URI under Expose an API, check that it matches the custom scope in sso.scopes, and check the tenant ID in sso.endpoints.

Frontend loop after the login

After the login, the browser keeps redirecting between the webclient and the login page. Possible causes:

  • offline_access is missing in sso.scopes.
Other errors

If your error is not among these, check the response of the login request in the developer tools. Entra ID often gives more information in the URL.

Troubleshooting

If the login fails, the user sees one of three symptoms: a pop-up with a SignatureException, a pop-up with an AuthenticationException, or a loop in the frontend after the login. To read the server response, open the browser developer tools (F12) before you log in.

AuthenticationException

A pop-up shows an AuthenticationException. The login request returns HTTP 401.

Cause: wrong client secret. The response is {"type":"AuthenticationException","params":[""]}, and the backend log has no entry. Check sso.clientSecret.

Frontend loop after the login

After the login, the browser keeps redirecting between the webclient and the login page. Possible causes:

  • userIdProperty is empty or does not match a claim of the token. The backend log contains java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "org.cibseven.webapp.auth.User.getId()" is null.
  • A component rejects the token that the webclient sends to the engine REST API (HTTP 401).
    • With the webclient SSO only: if sso.accessTokenToEngineRest is true, the webclient sends the access token of the identity provider. A servlet filter such as the composite authentication rejects it, because it only accepts tokens that are HMAC-signed with authentication.jwtSecret.
    • With OAuth2 on the engine REST API: if sso.accessTokenToEngineRest is false, the webclient sends its own HMAC-signed token, and Spring Security rejects it. Set the property to true.

On this Page: