Why Camunda Cockpit shows login when authorization is disabled?

When I disable the authorization by setting in Spring application.yml:
camunda.bpm.authorization.enabled: false
The Cockpit webapp shows the login dialog. Why?

We are running Camunda embedded and the Cockpit works well when authorization is enabled and with a ServletFilter we add a user to the identity service and perform a login through the UserAuthenticationResource. However, that was a temporarily hack as we didn’t got it to work with the authorization disabled.
Now we like to solve it properly and authorization should be disabled, and the hack filter removed, as we don’t use it as we have our own authentication/authorization handled through Spring Security, and enabling the authorization is a unnecessary performance burden (according to the Camunda doc’s)

The Backend calls that the cockpit performs to the backend are:

  1. https://domain.com/app/cockpit/ --> will forward to use the process engine in the url:
  2. https://domain.com/app/cockpit/

    … (include assets like js files)
  3. https://domain.com/api/engine/engine/ (to retrieve the process engine name (strange as was already in the url)
  4. https://domain.com/api/admin/auth/user/ -->>>> HTTP 404 —> shows login dialog
    The 404 is because the UserAuthenticationResource of Camunda doesn’t find any valid authentication object, which is correct as authorization is disabled :man_shrugging:

Please some help on how to solve this?

1 Like

Let us distinguish authorization (what permissions?) and authentication (who?). If you disable authorization then this means Camunda will not check if the user is allowed to say complete a task. However, it still needs to create an audit trail of who is interacting with the system when and hence needs to know who logged in (if you decide to not distinguish and use the same user for all interactions then this is your decision).

"with a ServletFilter we add a user to the identity service and perform a login through the UserAuthenticationResource. However, that was a temporarily hack "

So basically you are propagating the authentication from Spring Security to Camunda’s identity service?
Why is this a hack?

Is sounds very similar to the example given here:

With this setup I can hit http://localhost:8080 or http://localhost:8080/app/cockpit/default/#/dashboard, get the Spring Security login form and after a successful authentication land at http://localhost:8080/app/welcome/default/#!/welcome or http://localhost:8080/app/cockpit/default/#/dashboard.
It does not redirect me to the Camunda web app login screen.

Hi Rob, thanks for your response.

So basically you are propagating the authentication from Spring Security to Camunda’s identity service?
Why is this a hack?

  1. If we disable the authorization, the propagation of the user through the Servlet filter doesn’t work, which results Camunda showing a login dialog. Why?

  2. It’s a hack as we are creating a user, and add it to Camunda on the fly in the Servletfilter. That is: we check if the application user (from our own user system) doesn’t exists in Camunda (it’s started without any users), we create it, create a password and add the user, and we than perform a Login through the Camunda authentication (resource) service. We only allow that users exists at 1 place. How can we improve this? Or what is best practice here?
    (The security guys don’t like that we create passwords like this)

Does the “SpringSecurityAuthenticationProvider” overcomes that the user has to present in Camunda as well (LINK)

You are accessing http://localhost:8080/app/cockpit/default/#/dashboard or another url? If the authentication is setup correctly then you should not require a login page, with or without authorizations. I am not sure how exactly your approach is implemented. From version 7.9 onward the way to go about this is to implement a custom AuthenticationProvider. The SpringSecurityAuthenticationProvider shown illustrates this for a Spring Boot scenario.

Would you like to switch to this recommended approach and see if it work in your scenario?

You see that the SpringSecurity AutheticationFilte relies on Spring’s SecuritContextHolder:
SecurityContextHolder.getContext().getAuthentication();
The SSO step to integrate Spring security with your authentication mechanism is already covered?

Ad 2 - oh, I see. Of course replicating user accounts from an external user management into Camunda via own code accessing the IdentityService API is not desirable. The recommendation is to implement the IdentityProvider SPI: https://docs.camunda.org/manual/latest/user-guide/process-engine/identity-service/
This way Camunda can access your external identity provider, for instance in a read-only fashion, whenever it needs to check for the existence of a user with the ID it received via the AuthenticationProvider or requires user attributes. This mechanism does not require you to generate passwords for the users.

image
src: https://camunda.com/best-practices/securing-camunda/#_securing_camunda_with_strong_authentication_strong_and_strong_authorizations_strong

I was told you were an Enterprise customer. Please let us (CSM team, me) know in case you would like to discuss your project specifics on a call.

1 Like

Hi Rob,
Thanks for your details explanation.
Ad 1) I will create a AuthenticationProvider in the next days (also busy solving another urgent Camunda issue as the ProcessEngineFilter is executed too early, before the tenantId is set by another filter that is needed to retrieve the process engine)
How best to register the AuthenticationProvider such that it is run after the Spring security filters and that it’s used by Camunda?

Ad2) When do I need to implement a IdentityProvider? And if so, how to register in code? Do I need it when with authorization disabled? (= the desired situation).
I think I need to implement a IdentityProvider if I understand your picture correctly as it’s involved in performing authentication, but I would accept that the AuthenticationProvider would already be sufficient.
BTW: we don’t use the AuthenticationFiler in the picture. We have changed the Camunda web files like CamundaBpmWebappInitializer to support multitenancy and work with our own filters

The registration of the AuthenticationProvider is included in the example. You add a Spring configuration such as:

import org.camunda.bpm.webapp.impl.security.auth.ContainerBasedAuthenticationFilter;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import java.util.Collections;

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 15)
public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/app/**")
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .httpBasic();// this is just an example, use any auth mechanism you like

    }

    @Bean
    public FilterRegistrationBean containerBasedAuthenticationFilter(){

        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new ContainerBasedAuthenticationFilter());
        filterRegistration.setInitParameters(Collections.singletonMap("authentication-provider", "com.camunda.demo.filter.webapp.SpringSecurityAuthenticationProvider"));
        filterRegistration.setOrder(101); // make sure the filter is registered after the Spring Security Filter Chain
        filterRegistration.addUrlPatterns("/app/*");
        return filterRegistration;
    }
}

An IdentityProvider is required if you want to manage users in an external user repository instead of in the Camunda user repository. You stated that you currently create users in the Camunda user management on the fly using the IdentityService and wanted to remove this hack. If you want Camunda to read user info from your existing user repository then you need to implement an IdentityProvider.

Let me know how it goes. As mentioned, the named contact persons also have access to our enterprise support.

What is the minimum to be implemented of the ReadOnlyIdentityProvider interface in our case?

It involves quite some methods like createUserQuery(), and checkPassword(), etc… and I don’t see any reason why this should be called in our case with ContainerBasedAuthentication and authorization disabled.
Coul you please give some more insight in this, such that I know what I need to implement.

If you do not require any user information to be synced form the external user repository, then you do not need to implement the IdentityProvider. You can simply implement the AuthenticationProvider (as shown above) and register it (as shown above). This will take you past the login page (the issue you seem to face currently). Next, if authorizations are disabled, the user will be able to perform all operations. No groups or authorizations have to be configured.

Hi Rob, thanks for the details, a little status update from my side (some other urgent things came up in the meantime)
I worked it out, implemented it, and in theory it’s even quite simple. It seems to work, I just have some fine tuning to do as the ContainerBasedAuthenticationFilter uses different url’s then we use so it’s unable to retrieve the process engine from the url (I made similar changes to yours ProcessEnginesFilter to support multitenancy and different ur’s)
But I am confident that it will work, I will make final changes the coming days.
Thanks for the support.
What is the roadmap for the Camunda’s webapp? (like support for different urls’, that is an open issue for quite some time now, and easy integration in existing app (something like a lib in angular/react/…)

1 Like

Thanks for you feedback. I am glad this conversation helped. Do you already have ticket number for the “Support for different Urls” request? For an enterprise customer such a requests would be tracked in JIRA. If yes, please let me know and will follow up. If not, please provide details to ensure we cover your use case and I can create a ticket. You can also raise such request with our customer success team.

Here you find an existing issue about support for different url’s (web context): LINK