I’m trying to use Keycloak in my application. After having configured the server, I added a custom class (an extension of AuthenticationProvider) to the camunda-engine-rest-core where I retrieved the token from the request and used it for the authentication.
Everything seems to work but now I have to save the access token in order to use it later on in the process; e.g. for calling a Rest API from a Service Task.
I’ve read the article and “The last user credentials” option is exactly what I would like to do.
I don’t understand how to retrieve the last token for example when a user completes a task.
The article talks about ExecutionListener where I can access just the DelegateExecution object while I need the HTTP request (available in AuthenticationProvider) to retrieve the token.
For now, my solution is to receive the token as process variable when the front-end calls the engine (for Start and Complete operations) and use it in my tasks.
I think thats a viable way, however a challenge is secure storage of the token. If its compromised a malicious user could impersonate the real user. Hence storage as a process variable in the clear could be considered inappropriate. Another option for secure storage could be use of something like Hashicorp Vault…
Perhaps @BerndRuecker or another Camunda Representative may comment re this use case…
Hi Dario, it depends if you know that you will have synchronous calls going on, then you could store the token in some ThreadLocal or the like. But I guess you also want to have it available in the asynchronous case. As far as I recall we saved the token as process variable in the project which inspired the blog post back then. It is true, that due to security restrictions that might not be possible for you. It was no problem in this customers scenario though. You could also rely on an external storage where you link process instance id and token - but I have no out-of-my-mind recommendation. Sorry!
You wrote “calling a Rest API from a Service Task”. I assume you are trying to call a 3rd party ReST API secured by Keycloak from a Service Task.
IMHO you shouldn’t use user tokens as a means of trust between engine and 3rd party ReST API. The few downsides are: (1) tokens may expire at the moment you make the api call, (2) if stored in process instance, they are readable in cleartext.
Instead, I would setup a more direct trust between engine and API, e.g. create a client for engine in Keycloak, and use that to make calls from engine to API with engine credentials. To keep track of the user at API side, just convey that as extra context info in API calls.
In nutshell, you have to understand that Keycloak is itself a set of services:
a service, that gives you tokens in exchange for some (usually, static) id and secret.
various services, that you can call with that token, e.g. to manage users, or even create new clients dynamically.
Third party services, that also delegate step 1 to Keycloak and then authorize http requests with temporary tokens
So, e.g. Keycloak User Management API is not different from a 3rd party API that is secured by Keycloak.
If you want your Camunda be able to manage Keycloak users or call some other 3rd party APIs secured with Keycloak without human assistance, you will have to have some secret in Camunda app config that your app uses at runtime to obtain a temporary access token.
Yes, this became a very convoluted explanation, but OpenID Connect is a complex beast ))
Feel free to ask further questions.
PS: a good example of how to integrate Camunda properly with Keycloak is this plugin https://github.com/camunda/camunda-bpm-identity-keycloak. It has 2 parts: (1) authenticate users with JWT token, (2) present users info in camunda admin webapp. The second part accesses Keycloak user-management api with a privileged service account.