We have an application which is secured with a ResourceServer
and we are using GlobalMethodSecurity
to restrict access to API endpoints by client scope. This is all working as expected.
I am now trying to write some integration tests. In my tests I am manually creating a valid JWT and then making calls to the restricted endpoint. If I send no token I get a 401
as expected, but when I send a token that lacks the required scope it is not rejected but is able to hit the endpoint.
I presume that I am missing some configuration or setup to make the @PreAuthorize
work correctly, but I'm not sure exactly what I am missing.
Here is my test class:
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest
public class UserIT extends BaseIntegrationTest {
@Autowired
private UserRepository userRepository;
@Autowired
private WebApplicationContext wac;
@Autowired
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
@Before
public void setup () {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build();
}
@Test
public void cannotGetUsersWithoutToken () throws Exception {
mockMvc
.perform(get("/user/protected/user"))
.andExpect(status().isUnauthorized());
}
@Test
public void cannotGetUsersWithoutCorrectScope () throws Exception {
String token = getToken(Collections.singletonList("MY_ROLE"), 2);
mockMvc
.perform(get("/user/protected/user").header("Authorization", "Bearer " + token))
.andExpect(status().isUnauthorized());
}
}
And here's the API method:
@PreAuthorize("isAuthenticated() and #oauth2.hasScope('my-scope')")
@RequestMapping(value="/user", method = RequestMethod.GET)
public UserInfo getUser(){
long userId = getUserId();
return userService.retrieveUser(userId);
}
The first tests passes but the second fails; a 200
is returned instead of 401
.
Any suggestions as to what I'm missing would be appreciated. I have been following this https://www.baeldung.com/oauth-api-testing-with-spring-mvc.