Camunda Keycloak Identity Provider Plugin


#1

Hello everybody,

Camunda in its current version is perfectly suited to run BPM in cloud infrastructures. Identity management in the cloud, however, often differs from classical approaches. Camunda already provides a generic sample for Single Sign On when using Spring Boot. See https://github.com/camunda-consulting/code/tree/master/snippets/springboot-security-sso. From my point of view this is a good starting point, but SSO is only half the story.

At https://github.com/VonDerBeck/camunda-identity-keycloak I have therefore provided a ReadOnlyIdentityProvider for Keycloak. Something similar for Auth0 is in progress. Do you think this makes sense? Any remarks? Would that be an idea for a new Community Extension?

Cheers
Gunnar


#2

Gunnar,

Thank you for your contribution. The identity provider plugin is of a great help and our team has a head start. I believe Auth0 provider plugin will be of a great help to the community. One thing that i noticed is that when we integrated your Readonlyidentityprovider for keyCloak and haven’t done the SSO yet. We are using 7.10 Camunda version and getting the following error -

Caused by: java.lang.UnsupportedOperationException: This identity service implementation is read-only.
at org.camunda.bpm.engine.impl.cmd.AbstractWritableIdentityServiceCmd.execute(AbstractWritableIdentityServiceCmd.java:36) ~[camunda-engine-7.10.0.jar:7.10.0]

Any ideas?

Thanks,
Anand


#3

I see the following information. We are using Camunda Spring boot integration and so when the process engine starts, does it create a new user. Is this the reason why the readonly identity service is coming up?

Caused by: java.lang.UnsupportedOperationException: This identity service implementation is read-only.
at org.camunda.bpm.engine.impl.cmd.AbstractWritableIdentityServiceCmd.execute(AbstractWritableIdentityServiceCmd.java:36) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:27) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:106) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:45) ~[camunda-engine-spring-7.10.0.jar:7.10.0]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:43) ~[camunda-engine-spring-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:69) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:32) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.IdentityServiceImpl.newUser(IdentityServiceImpl.java:87) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.spring.boot.starter.configuration.impl.custom.CreateAdminUserConfiguration.createUser(CreateAdminUserConfiguration.java:101) ~[camunda-bpm-spring-boot-starter-3.2.0.jar:3.2.0]
at org.camunda.bpm.spring.boot.starter.configuration.impl.custom.CreateAdminUserConfiguration.postProcessEngineBuild(CreateAdminUserConfiguration.java:63) ~[camunda-bpm-spring-boot-starter-3.2.0.jar:3.2.0]
at org.camunda.bpm.engine.impl.cfg.CompositeProcessEnginePlugin.postProcessEngineBuild(CompositeProcessEnginePlugin.java:106) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl.invokePostProcessEngineBuild(ProcessEngineConfigurationImpl.java:1026) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl.buildProcessEngine(ProcessEngineConfigurationImpl.java:787) ~[camunda-engine-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.spring.SpringTransactionsProcessEngineConfiguration.buildProcessEngine(SpringTransactionsProcessEngineConfiguration.java:62) ~[camunda-engine-spring-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:54) ~[camunda-engine-spring-7.10.0.jar:7.10.0]
at org.camunda.bpm.engine.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:33) ~[camunda-engine-spring-7.10.0.jar:7.10.0]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
… 152 common frames omitted


#4

Hi Anand,

what does your configuration / application.yaml look like?

The identity provider is a ReadOnlyIdentityProvider (exactly like the LDAP Identity Provider) - therefore the engine must not create a user upon startup. If you have something like

camunda.bpm:
  admin-user:
    id: demo
    password: demo
    firstName: Camunda

in your configuration, this will try to create the admin user upon startup if not yet available. Please comment that out (the admin-user part). When using a ReadOnlyIdentityProvider you must create the admin user & group outside of Camunda.

I would recommend to create a Keycloak group camunda-admin and add a user assigned to this group.
You can then use the configuration attribute administratorGroupName of the plugin to make this group known to the engine.

If this is not your problem it would be very interesting to see your application.yaml.
And if this was your problem a feedback would be helpful as well - if necessary I would add a hint to the README of the plugin.

Cheers
Gunnar


#5

Hi Gunnar,

That was exactly my problem and i figured it out after couple of hours. Thanks for the information and it helps. I will try to add camunda-admin group to keycloak and it to my application.yaml file.

One more question that i have is about the SSO. I haven’t implemented the SSO yet as stated in the keyCloak Identity plugin provider. After removing the suggested demo user from the yaml file, my application ran fine. Only issue being, i can’t login with any user id although the users and groups are there in the keyCloak mainly camunda admin user.

plugin.identity.keycloak:

administratorUserId: camunda

Do i need to pass the authentication token? We have spring based basic authentication followed by camunda process engine?

Thanks,
Anand


#6

Hi Anand,

what about your Authorizations? See chapter Authorization Management in Camunda documentation.
The admin group/user will get its authorizations automatically, for any other group / user you will have to add the access rights either manually, in some piece of startup code, or from your deployment pipeline.

Regards
Gunnar


#7

What i noticed is that keycloakAdminUrl: in my yaml is the problem. The following property is wrong and this url is appended with /groups in the code which is throwing a an error 404 not found. I am using ```administratorGroupName: camunda-admin ithe yaml file.

keycloakAdminUrl: https:///auth/admin/realms/[master|]


Thanks again!!!

#8

When using the master realm this should be https://<your-keycloak-server>/auth/admin/realms/master.

Hint: the notation https://<your-keycloak-server>/auth/admin/realms/[master|<realm-name>] in the sample means “either master or your other realm-name” at the end of the url.

Thanks for your input, this helps to complete the docu and find other issues.

Cheers
Gunnar


#9

Unfortunately, the url https://<your-keycloak-server>/auth/admin/realms/master is not working in my case. My realm in keycloak is master. That is why, when /groups is appended, it is failing with 404 not found error. Just FYI.


#10

Everything is working fine now. When i assigned ‘admin’ to camunda-identity-service Service Account and it worked. I also noticed that administratorGroupName: camunda-admin worked and when i logged in as a user assigned to this admin group, all the OOTB applications (cockpit etc.,), I was able to see. But, if i just has administratorUserId: in yaml file, when i logged in as the user, it didn’t see any apps.

Thank you for your replies.


#11

Have you used the internal Keycloak ID when configuring administratorUserId? Currently it will work only that way. Sadly username is not equal ID. Within the next update I will enhance the configuration capabilities and check for username as well because this could be a common pitfall otherwise.

Thanks for the hint.


#12

Version 0.6.0-SNAPSHOT available with the following new features:

  • new flag useUsernameAsCamundaUserId for using the Keycloak username attribute as Camunda User ID
  • possibility to define the attribute administratorUserId using the admin’s username

#13

Thank you for this, this is a great piece of code.

Is there a sample project configured with SSO ? I’m having trouble configuring Spring Security for both the webapps and REST APIs in the same project.


#14

Hi QuentinC,

Currently I don’t have an abstract example project which already covers all aspects of SSO, even if I plan to provide one in the course of the next weeks or in the course of the summer.

Have you had a look at Camunda’s SSO samples already?
See https://github.com/camunda-consulting/code/tree/master/snippets/springboot-security-sso.
This includes the main aspects for securing the REST API as well.

When using Keycloak the only thing that changes slightly is how to extract the authenticated user / principal (which has been described in my README.md for the webapp, but should be similar for REST).

Regards
Gunnar


#15

Hi @VonDerBeck,
Any news about the example project ? I’m having trouble setting up a camunda - keycloak - spring boot project


#17

Hi @Tristan_MARIE ,

to give you at least a basic orientation on how to setup the Keycloak Identity Provider I have provided a first very simple sample project on https://github.com/VonDerBeck/camunda-showcase-keycloak.

It does not yet include a full kubernetes setup - but already showcases the connection to a local running Keycloak Server. SSO setup for Cockpit/Tasklist/Admin is included. Yet missing is a more detailed description of the setup and configuration. But hope this helps anyway.

Cheers
Gunnar


#18

Thanks a lot ! I made it fully work (with the REST API aswell) with a bit of tuning, I changed the KeycloakAuthenticationProvider so it can detect if there is a Bearer token, if so, it extracts the user email from it and turn an AuthenticationResult :slight_smile:
Feel free to ask the code if you want it


#19

Hi @Tristan_MARIE

I’m glad to hear you’ve been successful :smiley:. Of course I’m interested in what you have changed and why - and would be happy if you share your changes.

Many greetings
Gunnar


#20

Meanwhile the Showcase for the Keycloak Camunda Identity Provider Plugin contains a first basic kubernetes setup which might help you as well. It’s a quickstart, the description will improve in the future.

Cheers
Gunnar


#21

Hello Gunnar,

That is a great project you have created. We believe it would be a good fit for a community extension, so please let us know if you would like to take that step.

The transition to a community extension would involve the following:

  1. Transferring the repository to the camunda github organization
  2. Setting up Camunda continuous integration builds for the extension
  3. Making the project ready to be released on Maven central
  4. Moving the Maven coordinates into the org.camunda.bpm.extension namespace

We would take care of these steps or help you perform them.

Once a community extension, you can benefit from the following:

  • Releases to Maven central via the Camunda organization, so no need to deal with Maven central yourself
  • Possibility to publish posts on blog.camunda.org about your extension
  • Better visibility in the Camunda community

Cheers,
Thorben