question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using annotations in a cucumber test environment with MockMvcSupport does not create a Principal in Spring Boot

See original GitHub issue

Describe the bug We have Keycloak configured in our Spring Boot micro-service. We use Cucumber to test our backend rest service endpoints. We use JWT tokens to secure endpoints. I use a very simple @WithMockKeycloakAuth({ “ROLE_user” }) annotation. When stepping in the controller, the Principal was not created (null). Hence, the annotation on a service method @RolesAllowed(“user”) fails.

Code sample

  1. failing test
@WithMockKeycloakAuth({ "ROLE_user" })
    public List<ProductLightDTO> securedProductSearch(ProductFilter filter, String username, String password) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String body = objectMapper.writeValueAsString(filter);
        MvcResult result = api.perform(post("/products").contentType(APPLICATION_JSON_UTF8)
                .content(body)).andReturn();
        List<ProductLightDTO> productLightDTOS = Arrays.asList(objectMapper.readValue(result.getResponse().getContentAsString(), ProductLightDTO.class));
        return productLightDTOS;
    }
  1. Component under test
@RestController
@RequestMapping("/products")
public class ProductController {

    private final ProductService productService;

    @PostMapping("")
    public List<ProductLightDTO> searchProducts(@RequestBody ProductFilter productFilter, Principal principal) {
        return productService.search(productFilter);
    }

The service method (never gets ther since Spring Security is doing it’s job)

@Service
@Log4j2
public class ProductService {

    @RolesAllowed("user")
    public List<ProductLightDTO> search(ProductFilter productFilter) {
..
    }
  1. spring-security configuration involved (runtime and tests)

Runtime config:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.cors().and().authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        http.csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

}

Test config:

@Component
@Import({ ServletKeycloakAuthUnitTestingSupport.UnitTestConfig.class })
public class SearchApi {
...
    @Autowired
    MockMvcSupport api;

    @WithMockKeycloakAuth({ "ROLE_user" })
    public List<ProductLightDTO> securedProductSearch(ProductFilter filter) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        String body = objectMapper.writeValueAsString(filter);
        MvcResult result = api.perform(post("/products").contentType(APPLICATION_JSON_UTF8)
                .content(body)).andReturn();
        List<ProductLightDTO> productLightDTOS = Arrays.asList(objectMapper.readValue(result.getResponse().getContentAsString(), ProductLightDTO.class));
        return productLightDTOS;
    }

Expected behavior

I expect to find a Principal in the controler with a role “user”.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:27 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
ch4mpycommented, Oct 14, 2021

don’t bother with the sample. I built one and figured out why security is not working: WithSecurityContextTestExecutionListener is not triggered by Cucumber JUnit test runner.

I oppened a ticket on Cucumber-jvm: https://github.com/cucumber/cucumber-jvm/issues/2408

1reaction
ch4mpycommented, Oct 13, 2021

It is in your runtime config, but I can’t see your WebSecurityConfig referenced in test configuration you provided.

If you share a small project, I might add it to samples in tests once we have it working.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cucumber Tests in Spring Boot with Dependency Injection
The @CucumberContextConfiguration annotation tells Cucumber to use this class as the test context configuration for Spring. In our case, we don' ...
Read more >
Set Up and Run Cucumber Tests In Spring Boot Application
Step 1: Create a Spring Boot Project using Spring Initializer. ... '@CucumberOptions' annotation is used to configure the directory that ...
Read more >
46. Testing - Spring
Test annotations are already annotated with it. By default, @SpringBootTest will not start a server. You can use the webEnvironment attribute of @SpringBootTest...
Read more >
Spring Cucumber ActiveProfiles annotation ... - Stack Overflow
I've solved the issue by separating the packages a bit, and creating separate StepInitializer classes for both testsets. Current setup: Test ...
Read more >
Four Methods to Disable Spring Security in JUnit Tests
Execute the tests with Spring Security using Mock Authentication. ... does not prevent auto-detection of @SpringBootConfiguration .
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found