Why my test passes without a bearer token
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?
Solution 1:
@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.