Authorization does not apply to REST API

After learning a lot about filters and digging in the code and the docs, I finally got it. Since it took me a lot of time, I’ll try to explain it for other Camunda/Spring Boot newbies.

We need acutally 3 servlet filters:

  1. The Spring security filter chain
  2. ContainerBasedAuthenticationFilter (from org.camunda.bpm.webapp.impl.security.auth)
  3. ProcessEngineAuthenticationFilter (from org.camunda.bpm.engine.rest.security.auth)

The Spring security filter chain is responsible for authentication on the level of the Spring Boot application. It writes the authentication result to the general Spring SecurityContext, the Camunda engine does not know about it.

The second and third filter are responsible for writing the authentication to the Camunda engine. If there is no authentication written to the engine, the engine won’t check authorization.

  • The ContainerBasedAuthenticationFilter only applies to APIs belonging to the web apps (routes starting with /app or /api),
  • The ProcessEngineAuthenticationFilter only applies to the REST API.

Except applying to different URLs, the second and third filter work pretty similar. Both expect an authenciation provider as init parameter.
This means you have to specify a class implementing org.camunda.bpm.engine.rest.security.auth.AuthenticationProvider. In this class you have to construct a org.camunda.bpm.engine.rest.security.auth.AuthenticationResult.

In short, the AuthenticationProvider is responsible for translating the Spring SecurityContext to a Camunda authentication, thus enabling authorization for the Camunda engine.

Here is a snippet how to register the filters in java code:

    // Register the servlet filter for the WebApps
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean containerBasedAuthenticationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new ContainerBasedAuthenticationFilter());
        filterRegistration
                .setInitParameters(Collections.singletonMap("authentication-provider", WebAppAuthProvider.class.getCanonicalName()));
        filterRegistration.setOrder(102); // make sure the filter is registered after the Spring Security Filter Chain
        filterRegistration.addUrlPatterns("/camunda/app/*" , "/camunda/api/*");
        return filterRegistration;
    }
    
    // Register the servlet filter for the REST API
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean camundaRestAuthFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new ProcessEngineAuthenticationFilter());
        filterRegistration
        .setInitParameters(Collections.singletonMap("authentication-provider", RestApiAuthProvider.class.getCanonicalName()));
        filterRegistration.setOrder(103); // make sure the filter is registered after the Spring Security Filter Chain
        filterRegistration.addUrlPatterns("/engine-rest/*");
        return filterRegistration;
    }
5 Likes