I’m encountering a 403 Forbidden error when running a Spring Boot test for my SetupController using MockMVC. Despite mocking the JWT validation to return true, the test still fails with a 403 status. Below are the relevant code snippets for my controller and test class.
SetupController.java:
@RestController
@RequestMapping("/rest/setup")
public class SetupController {
@PostMapping("/createSummary")
@ResponseStatus(value = HttpStatus.OK)
@PreAuthorize("hasAuthority('USER') or hasAuthority('ADMIN')")
public void createChallengeSummary(@RequestHeader String Authorization) {
if (!jwtValidator.isValidJWT(Authorization)) {
LOGGER.error("Invalid JWT Token");
return;
}
String userEmail = jwtValidator.getUserEmail(Authorization.substring(7));
LOGGER.info("Creating ChallengeSummary for user with Email: {}", userEmail);
reportsService.createChallengeSummary(userEmail);
}
}
SetupControllerTest.java:
@WebMvcTest(SetupController.class)
public class SetupControllerTest {
private final String AUTH_HEADER = "Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhbGV4QGZobXMuZGUiLCJhdXRoIjoiVVNFUiIsImlhdCI6MTcxNjkwMTAxMiwiZXhwIjo0ODcwNTAxMDEyfQ.YgqbpgTBpRSmPMAY1-t9UVXAvIVigEjKSHeM8axslIGVFUozeacYfb3VLPvGJ99RWf3C8q5UjMmhpBEAPlzVgyHUFhj_6NUHkYuTcFFGIvdAClQ00RIIbNhx0g23PrQFo7AZtF1m6BbLe6QQUU12gEH4XYq4hL0p4BV9iNRnSdSHK-vLGuP9jSLFwOQRzMkWEBMfvn6w4mQWlQuBG9Zi6hjg5b4meOHUvQJeVr_sAHq2e15ig292ndisAVbQ1VP6-91-qpmOQ4-O36o_DUUVCaSDV4Gup9lE4Deu0UPdaYTR0UuSmfZx0e3DnQufwKUokqNUwdgzfRnwLIvXekgwAA";
private final String TEST_USER_EMAIL = "[email protected]";
@BeforeEach
public void setUp() throws Exception {
UserDetails userDetails = User.withUsername(TEST_USER_EMAIL)
.password("***")
.authorities("USER", "ADMIN")
.build();
when(jwtValidator.isValidJWT(any(String.class))).thenReturn(true);
when(jwtValidator.getUserEmail(any(String.class))).thenReturn(TEST_USER_EMAIL);
when(jwtValidator.resolveToken(any(HttpServletRequest.class))).thenReturn(AUTH_HEADER.substring(7));
when(jwtValidator.getAuthentication(any(String.class)))
.thenReturn(new UsernamePasswordAuthenticationToken(userDetails, "",
userDetails.getAuthorities()));
}
@Test
public void testCreateChallengeSummary() throws Exception {
this.mvc.perform(post("/rest/setup/createSummary")
.header("Authorization", AUTH_HEADER))
.andExpect(status().isOk())
.andDo(print());
verify(reportsService).createChallengeSummary(TEST_USER_EMAIL);
}
}
JWTValidator.java:
@Component
public class JwtValidator {
public boolean isValidJWT(String jwt) {
try {
Jwts.parser()
.verifyWith(publicKey)
.build()
.parseSignedClaims(jwt);
return true;
} catch (Exception e) {
LOG.info("Token rejected because " + e.getMessage());
throw new InvalidException("JWT invalid");
}
}
public Authentication getAuthentication(String jwt) {
return new UsernamePasswordAuthenticationToken(getUserEmail(jwt), "", getRoles(jwt));
}
public String getUserEmail(String jwt) {
final Jws<Claims> token = Jwts.parser()
.verifyWith(publicKey)
.build()
.parseSignedClaims(jwt);
final Claims payload = token.getPayload();
return payload.getSubject();
}
/**
* Extracts the user roles from a JWT.
*
* @param jwt
* @return
*/
public Collection<GrantedAuthority> getRoles(String jwt) {
Collection<GrantedAuthority> result = new ArrayList<>();
final Jws<Claims> token = Jwts.parser()
.verifyWith(publicKey)
.build()
.parseSignedClaims(jwt);
final Claims payload = token.getPayload();
final String authClaim = payload.get("auth", String.class);
if (authClaim.equals("USER")) {
result.add(Role.USER);
} else if (authClaim.equals("ADMIN")) {
result.add(Role.ADMIN);
}
return result;
}
public PublicKey getPublicKey() {
return this.publicKey;
}
}
- Mocking JwtValidator to always return true for isValidJWT.
- Ensuring the Authorization header is correctly passed in the request.
- Mocking the user details with appropriate authorities.
Issue:
Despite these setups, the test still results in a 403 Forbidden error.
Questions:
- Is there something wrong with my test setup or Spring Security configuration?
- Are there additional configurations needed for Spring Security to allow the mock setup to work properly?
Any help or guidance would be greatly appreciated. Thank you!