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.