Identity Service

The identity service is an API abstraction over various user/group repositories. The basic entities are

  • User: a user identified by a unique Id
  • Group: a group identified by a unique Id
  • Membership: the relationship between users and groups
  • Tenant: a tenant identified by a unique Id
  • Tenant Membership: the relationship between tenants and users/groups

Example:

User demoUser = processEngine.getIdentityService()
  .createUserQuery()
  .userId("demo")
  .singleResult();

CIB seven distinguishes between read-only and writable user repositories. A read-only user repository provides read-only access to the underlying user/group database. A writable user repository allows write access to the user database which includes creating, updating and deleting users and groups.

To provide a custom identity provider implementation, the following interfaces can be implemented:

Custom Whitelist for User, Group and Tenant IDs

User, Group and Tenant IDs can be matched against a Whitelist Pattern to determine if the provided ID is acceptable or not. The default (global) Regular Expression pattern to match against is "[a-zA-Z0-9]+|camunda-admin" i.e. any combination of alphanumeric values or ‘camunda-admin’.

If your organisation allows the usage of additional characters (ex.: special characters), the ProcessEngineConfiguration propery generalResourceWhitelistPattern should be set with the appropriate pattern in the engine’s configuration file. Standard Java Regular Expression syntax can be used. For example, to accept any character, the following property value can be used:

<property name="generalResourceWhitelistPattern" value=".+"/>

The definition of different patterns for User, Group and Tenant IDs is possible by using the appropriate configuration propery:

<property name="userResourceWhitelistPattern" value="[a-zA-Z0-9-]+" />
<property name="groupResourceWhitelistPattern" value="[a-zA-Z]+" />
<property name="tenantResourceWhitelistPattern" value=".+" />

Note that if a certain pattern isn’t defined (ex. the tenant whitelist pattern), the general pattern will be used, either the default one ("[a-zA-Z0-9]+|camunda-admin") or one defined in the configuration file.

The Database Identity Service

The database identity service uses the process engine database for managing users and groups. This is the default identity service implementation used if no alternative identity service implementation is provided.

The database identity service implements both ReadOnlyIdentityProvider and WritableIdentityProvider providing full CRUD functionality in Users, Groups and Memberships.

The LDAP Identity Service

The LDAP identity service provides read-only access to an LDAP-based user/group repository. The identity service provider is implemented as a Process Engine Plugin and can be added to the process engine configuration. In that case it replaces the default database identity service.

To use the LDAP identity service, the camunda-identity-ldap.jar library has to be added to the classloader of the process engine.

Please import the CIB seven BOM to ensure correct versions for every CIB seven project.

<dependency>
  <groupId>org.cibseven.bpm.identity</groupId>
  <artifactId>cibseven-identity-ldap</artifactId>
</dependency>

Activate the LDAP Plugin

The following is an example of how to configure the LDAP Identity Provider Plugin using Spring XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="processEngineConfiguration" class="org.cibseven.bpm.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
    ...
    <property name="processEnginePlugins">
      <list>
        <ref bean="ldapIdentityProviderPlugin" />
      </list>
    </property>
  </bean>
  <bean id="ldapIdentityProviderPlugin" class="org.cibseven.bpm.identity.impl.ldap.plugin.LdapIdentityProviderPlugin">
    <property name="serverUrl" value="ldap://localhost:3433/" />
    <property name="managerDn" value="uid=daniel,ou=office-berlin,o=camunda,c=org" />
    <property name="managerPassword" value="daniel" />
    <property name="baseDn" value="o=camunda,c=org" />

    <property name="userSearchBase" value="" />
    <property name="userSearchFilter" value="(objectclass=person)" />
    <property name="userIdAttribute" value="uid" />
    <property name="userClass" value="person" />
    <property name="userFirstnameAttribute" value="cn" />
    <property name="userLastnameAttribute" value="sn" />
    <property name="userEmailAttribute" value="mail" />
    <property name="userPasswordAttribute" value="userpassword" />

    <property name="groupSearchBase" value="" />
    <property name="groupSearchFilter" value="(objectclass=groupOfNames)" />
    <property name="groupIdAttribute" value="ou" />
    <property name="groupNameAttribute" value="cn" />
    <property name="groupMemberAttribute" value="member" />

    <property name="authorizationCheckEnabled" value="false" />

    <!-- Optional LDAP cache, disabled by default -->
    <property name="cacheEnabled" value="false" />
    <property name="cacheUserQueriesTtlSeconds" value="30" />
    <property name="cacheUserQueriesMaxWeight" value="20000" />
    <property name="cacheGroupTtlSeconds" value="120" />
    <property name="cacheGroupMaxWeight" value="8000" />
    <property name="cacheStatsLogEnabled" value="false" />
    <property name="cacheStatsLogInterval" value="1000" />
  </bean>
</beans>

The following is an example of how to configure the LDAP Identity Provider Plugin in bpm-platform.xml/processes.xml:

<process-engine name="default">
  <job-acquisition>default</job-acquisition>
  <configuration>org.cibseven.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration</configuration>
  <datasource>java:jdbc/ProcessEngine</datasource>

  <properties>...</properties>

  <plugins>
    <plugin>
      <class>org.cibseven.bpm.identity.impl.ldap.plugin.LdapIdentityProviderPlugin</class>
      <properties>

        <property name="serverUrl">ldap://localhost:4334/</property>
        <property name="managerDn">uid=jonny,ou=office-berlin,o=camunda,c=org</property>
        <property name="managerPassword">s3cr3t</property>

        <property name="baseDn">o=camunda,c=org</property>

        <property name="userSearchBase"></property>
        <property name="userSearchFilter">(objectclass=person)</property>

        <property name="userIdAttribute">uid</property>
        <property name="userClass">person</property>
        <property name="userFirstnameAttribute">cn</property>
        <property name="userLastnameAttribute">sn</property>
        <property name="userEmailAttribute">mail</property>
        <property name="userPasswordAttribute">userpassword</property>

        <property name="groupSearchBase"></property>
        <property name="groupSearchFilter">(objectclass=groupOfNames)</property>
        <property name="groupIdAttribute">ou</property>
        <property name="groupNameAttribute">cn</property>

        <property name="groupMemberAttribute">member</property>

        <property name="authorizationCheckEnabled">false</property>

        <!-- Optional LDAP cache, disabled by default -->
        <property name="cacheEnabled">false</property>
        <property name="cacheUserQueriesTtlSeconds">30</property>
        <property name="cacheUserQueriesMaxWeight">20000</property>
        <property name="cacheGroupTtlSeconds">120</property>
        <property name="cacheGroupMaxWeight">8000</property>
        <property name="cacheStatsLogEnabled">false</property>
        <property name="cacheStatsLogInterval">1000</property>

      </properties>
    </plugin>
  </plugins>

</process-engine>

Administrator Authorization Plugin

The LDAP Identity Provider Plugin is usually used in combination with the Administrator Authorization Plugin which allows you to grant administrator authorizations for a particular LDAP User/Group.

Multi-Tenancy

Currently, the LDPA Identity Service doesn’t support multi-tenancy. That means it is not possible to get tenants from LDAP and the transparent multi-tenancy access restrictions don’t work by default.

Configuration Properties of the LDAP Plugin

The LDAP Identity Provider provides the following configuration properties:

Property Description
serverUrl The url of the LDAP server to connect to.
managerDn The absolute DN of the manager user of the LDAP directory.
managerPassword The password of the manager user of the LDAP directory
baseDn

The base DN: Identifies the root of the LDAP directory. Is appended to all DN names composed for searching for users or groups.

Example: o=camunda,c=org

userSearchBase

Identifies the node in the LDAP tree under which the plugin should search for users. Must be relative to baseDn.

Example: ou=employees

userSearchFilter

LDAP query string used when searching for users. Example: (objectclass=person)

userIdAttribute

Name of the user Id property. Example: uid

userClass

LDAP attribute when searching for users. Example: person

userFirstnameAttribute

Name of the firstname property. Example: cn

userLastnameAttribute

Name of the lastname property. Example: sn

userEmailAttribute

Name of the email property. Example: mail

userPasswordAttribute

Name of the password property. Example: userpassword

groupSearchBase

Identifies the node in the LDAP tree under which the plugin should search for groups. Must be relative to baseDn.

Example: ou=roles

groupSearchFilter

LDAP query string used when searching for groups. Example: (objectclass=groupOfNames)

groupIdAttribute

Name of the group Id property. Example: ou

groupNameAttribute

Name of the group Name property. Example: cn

groupTypeAttribute

Name of the group Type property. Example: cn

groupMemberAttribute

Name of the member attribute. Example: member

acceptUntrustedCertificates

Accept of untrusted certificates if LDAP server uses SSL. Warning: We strongly advise against using this property. Better install untrusted certificates to JDK key store.

useSsl

Set to true if LDAP connection uses SSL. Default: false

initialContextFactory

Value for the java.naming.factory.initial property. Default: com.sun.jndi.ldap.LdapCtxFactory

securityAuthentication

Value for the java.naming.security.authentication property. Default: simple

usePosixGroups

Indicates whether posix groups are used. If true, the connector will use a simple (unqualified) user id when querying for groups by group member instead of the full DN. Default: false

allowAnonymousLogin

Allows to login anonymously without a password. Default: false

Warning: We strongly advise against using this property. You should configure your LDAP to use simple authentication without anonymous login.

authorizationCheckEnabled

If this property is set to true, then authorization checks are performed when querying for users or groups. Otherwise authorization checks are not performed when querying for users or groups. Default: true

Note: If you have a huge amount of LDAP users or groups we advise to set this property to false to improve the performance of the user and group query.

sortControlSupported

If this property is set to true, then ordering of the search results is enabled. Otherwise orderBy clauses in search queries are simply ignored. Default: false

Note: The support of search result ordering is not be implemented by every LDAP server. Make sure that your currently used LDAP Server implements the RFC 2891.

pageSize

When you define a number higher or equal to 1, pagination is enabled, and results are loaded page per page. Therefore, the query sent to the LDAP Server expects support for the LDAPv3 Control for paged results as defined in RFC 2696.
Default: null (no pagination)

Note:

  • By default, some LDAP Server implementations refuse to serve an unbounded number of results in one response. Therefore, configuring this property is mandatory to circumvent the limit of results.
  • This parameter does not affect the UI or the number of results returned via Java or REST API since it uses an auto-pagination approach.

passwordCheckCatchAuthenticationException

When a login attempt fails with an AuthenticationException, by default, the plugin catches this exception and marks the password check as failed. You can choose to set this flag to `false` which will cause the plugin to re-throw the AuthenticationException. This is helpful when you want to register a frontend plugin that reacts to the exception message from the login attempt. Default: true

cacheEnabled

Enables LDAP query result caching. Default: false

cacheUserQueriesTtlSeconds

Time to live in seconds for cached user-query results (for high-cardinality, rarely-repeated user searches). Default: 30

cacheUserQueriesMaxWeight

Maximum total cache weight for user-query results. Each entry weight equals the size of its result list (minimum 1), so this limits cached users rather than distinct queries. Default: 20000

cacheGroupTtlSeconds

Time to live in seconds for cached group lookup results (for low-cardinality, frequently-repeated group lookups). Default: 120

cacheGroupMaxWeight

Maximum total cache weight for group lookup results. Each entry weight equals the size of its result list (minimum 1), so this limits cached groups rather than distinct queries. Default: 8000

cacheStatsLogEnabled

Enables periodic INFO logging of cache hit/miss statistics for debugging purposes. Default: false

cacheStatsLogInterval

Defines how often (in cache lookups) the cache statistics summary is logged when cacheStatsLogEnabled is true. Default: 1000

Performance of the LDAP Plugin

Every user and group lookup of the LDAP identity service is a live search against the directory server – the plugin keeps no local copy of users and groups. Two things therefore dominate the response time of the web applications and of every authorization check: how much of the directory a single query has to touch, and whether results are cached.

Keep the user and group search narrow

If userSearchBase/groupSearchBase point at the root of the directory and the search filters only restrict the object class, every query scans the whole directory. This happens on each login, on each page render that resolves user names, and for each authorization check.

Restrict both the searched subtree and the filter to the entries CIB seven actually needs:

<property name="groupSearchBase">ou=cibseven,ou=roles</property>
<property name="groupSearchFilter">(&amp;(objectclass=groupOfNames)(cn=cibseven-*))</property>

Note that &amp; is the XML escape for the LDAP AND operator & – written as a plain &, the configuration file would not be valid XML.

groupSearchFilter is combined with an AND into every group query, including the “which groups does this user belong to” lookup that runs on login. A user who is a member of several hundred directory groups then only yields the CIB seven ones, instead of all of them being fetched, transformed and authorization-checked. The same applies to userSearchBase and userSearchFilter.

Fewer groups per user also make the engine’s own authorization checks cheaper, because every group of the authenticated user ends up in the database query performing the check. See Identity Provider.

Two further properties matter here: pageSize is mandatory if your LDAP server refuses to serve unbounded result sets, and authorizationCheckEnabled can be set to false to skip the per-result authorization check on large directories.

Caching

Caching is disabled by default. With cacheEnabled set to true, the plugin keeps LDAP query results in memory, in two independently sized cache groups:

Cache group Caches Properties (defaults)
User queries Searches by id, name or email. Many distinct keys, each rarely repeated – sized large, expires quickly. cacheUserQueriesTtlSeconds (30)
cacheUserQueriesMaxWeight (20000)
Group lookups Group queries and the members of a group. Few distinct keys, hit repeatedly by page renders and authorization checks – sized small, kept longer. cacheGroupTtlSeconds (120)
cacheGroupMaxWeight (8000)

How it works:

  • Each entry expires individually once its TTL has passed since it was written. There is no background refresh – the first query after expiry hits LDAP again.
  • The caches are bounded by weight, not by entry count. An entry weighs as many units as its result list has elements (an empty result counts as 1). maxWeight therefore limits how many users or groups stay resident, so one broad query returning thousands of users cannot exhaust the heap.
  • Passwords are never cached. checkPassword always authenticates against LDAP.
  • The caches live in the memory of the process engine. In a cluster, every node has its own.

Choosing the parameters:

  • The TTL is your staleness window: a user or a membership changed in LDAP becomes visible after at most TTL seconds. Shorten it for directories that change often.
  • Raise cacheGroupTtlSeconds first. Group membership drives the authorization checks, is queried constantly and usually changes rarely.
  • Size maxWeight by the number of user and group objects you want to keep resident, not by the number of queries you expect.
  • Paginated results are cached per page. If entries are added, removed or reordered in LDAP between two page fetches, the pages can skew. Keep the TTL short if exact consistency across pages matters.
  • To validate a setting, switch on cacheStatsLogEnabled. Hit/miss statistics are then logged at INFO every cacheStatsLogInterval lookups. Increase TTL and weight as long as the hit ratio still improves.

The OAuth2 Identity Service

See the Spring Security OAuth2 Integration’s OAuth2 Identity Provider documentation.

The SCIM2 Identity Service

The SCIM2 identity service provides access to a SCIM 2.0 compliant user and group repository. It is implemented as a Process Engine Plugin and can replace the default database identity service.

The SCIM2 identity service is primarily read-oriented and is intended for integrating CIB seven with external SCIM 2.0 compliant providers.

To use the SCIM2 identity service, add the cibseven-identity-scim library to the process engine classpath.

Activate the SCIM2 Plugin

The following is an example of how to configure the SCIM2 Identity Provider Plugin in bpm-platform.xml for Tomcat:

<process-engine name="default">
  <job-acquisition>default</job-acquisition>
  <configuration>org.cibseven.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration</configuration>
  <datasource>java:jdbc/ProcessEngine</datasource>

  <plugins>
    <plugin>
      <class>org.cibseven.bpm.identity.impl.scim.plugin.ScimIdentityProviderPlugin</class>
      <properties>
        <property name="serverUrl">https://scim.example.com</property>
        <property name="authenticationType">oauth2</property>
        <property name="oauth2TokenUrl">https://auth.example.com/oauth/token</property>
        <property name="oauth2ClientId">your-client-id</property>
        <property name="oauth2ClientSecret">your-client-secret</property>
        <property name="verbose">true</property>
      </properties>
    </plugin>
  </plugins>
</process-engine>

The plugin also supports basic authentication and OAuth2 client credentials. For production use, keep SSL/TLS enabled and configure the authentication method that fits your SCIM server.

SCIM2 Plugin Configuration Properties

The SCIM2 Identity Provider Plugin provides the following configuration properties:

Property Description
serverUrl The base URL of the SCIM server.
authenticationType The authentication type used for the SCIM connection: bearer, basic, or oauth2.
bearerToken The bearer token used when authenticationType is set to bearer.
username The username used when authenticationType is set to basic.
password The password used when authenticationType is set to basic.
oauth2TokenUrl The OAuth2 token endpoint URL used when authenticationType is set to oauth2.
oauth2ClientId The OAuth2 client ID.
oauth2ClientSecret The OAuth2 client secret.
userAuthenticationEnabled Enables user authentication via SCIM or OIDC. The default value is false.
userIdAttribute The SCIM attribute used as the user ID.
userFirstnameAttribute The SCIM attribute used as the user first name.
userLastnameAttribute The SCIM attribute used as the user last name.
userEmailAttribute The SCIM attribute used as the user email address.
groupIdAttribute The SCIM attribute used as the group ID.
groupNameAttribute The SCIM attribute used as the group name.
groupMemberAttribute The SCIM attribute used to resolve group members.
acceptUntrustedCertificates Accepts self-signed certificates. This is not recommended for production.
useSsl Enables SSL/TLS for the SCIM connection. The default value is true.
authorizationCheckEnabled Enables authorization checks when querying users or groups. The default value is true.
pageSize The number of results to load per page. The default value is 100.

Additional Notes

The plugin supports user and group queries, pagination, and configurable attribute mappings. Basic user and group management is intended for use in test environments only. In production, manage users and groups in the SCIM server itself.

Throttle login attempts

A mechanism exists for preventing subsequent unsuccessful login attempts.The essence of it is that the user is not able to log in for a specific amount of time after unsuccessful login attempts. The amount of time is calculated after each attempt but it is limited by maximum delay time. After a predefined number of unsuccessful attempts, the user will be locked and only an administrator has permissions to unlock them.

The mechanism is configurable with the following properties and respective default values.

  • loginMaxAttempts=10
  • loginDelayFactor=2
  • loginDelayMaxTime=60
  • loginDelayBase=3

For more information, please check the process engine’s login properties section.

Calculation of the delay is done via the formula: baseTime * factor^(attempt-1). The behaviour with the default configuration will be: 3 seconds delay after the first unsuccessful attempt, 6 seconds after the 2nd attempt, 12 seconds, 24 seconds, 48 seconds, 60 seconds, 60 seconds, etc. After the 10th attempt, if the user fails to login again, the user will be locked.

LDAP specifics

If you have a LDAP setup on your engine, you need to handle the throttling on the LDAP side. The login mechanism in your system will not be affected by the above properties.

On this Page: