I have a simple Spring app. But I don’t understand why the test passes without the need of a bearer token.
Here is the controller:
... @GetMapping @PreAuthorize("hasAuthority('app-user')") public ResponseEntity<List<FooDTO>> findAll(){ return ResponseEntity.ok(fooService.findAll()); }
Security Configuration:
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) @PropertySource("classpath:application-${env}.yml") static class OAuth2SecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(); http.cors(); http.csrf().disable(); } }
In order to setup the security configs for tests I’m using:
@TestConfiguration @Import({OAuth2SecurityConfigurerAdapter.class}) public class DefaultTestConfiguration { }
So my test class looks like this:
@AutoConfigureMockMvc @ContextConfiguration(classes = {FooController.class}) @WebMvcTest @ActiveProfiles("test") @Import(DefaultTestConfiguration.class) public class FooIntegrationTest { @Test @WithMockUser(authorities = "app-user") public void findAllShouldReturnAList() throws Exception { MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/foos") .accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultHandlers.print()) .andExpect(status().isOk()) .andReturn(); assertThat(result.getResponse()).isNotNull(); } }
If I change the autority in the test to something like ‘foo-user’ the response becomes 403, as expected, and because of that I think that the security configuration is being applied.
If I test the application with Postman the bearer token is needed to run requests, but why its not needed in the test?
Advertisement
Answer
@WithMockUser annotation does not do authentication. (Please note, you even did not provide a user name.) It creates a new default user with user/password name and passwords and this user is authenticated already with a UsernamePasswordAuthenticationToken. And you provided the authority for this default user/password user in your @WithMockUser(authorities = “app-user”) annotation as “app-user”. https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/test/context/support/WithMockUser.html
So the user you run your test has authentication and authorization.
Your security configuration is NOT being applied. Again, @WithMockUser creates new empty security context with SecurityContextHolder.createEmptyContext() with security defaults. https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/test/context/support/WithMockUser.html
And when you use Postman all that does not happen of course and you real user must be authenticated with normal bearer token.