I came up with this issue when i added /admin endpoint to antMatchers("/admin").hasAuthority("ADMIN")
it simply won't make a GET request to /admin and return 200 it returns 403 instead
Note: i'm using JWT as an extra layer of authentication.
This is my security config
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/", "/health", "/authority", "/dashboard", "/users/login", "/logoutUser", "/manageEvents", "/manageAeds", "/manageReports",
"/charts", "/error", "/profile", "/authenticate/**", "/login", "/403", "/userProfile", "/deleteAed", "/users/add").permitAll()
.antMatchers("/admin").hasAuthority("ADMIN")
.antMatchers("/css/**", "/img/**", "/js/**", "/images/**", "/error_css/**", "/scss/**", "/vendor/**").permitAll()
.anyRequest().authenticated().and().
exceptionHandling().accessDeniedPage("/403").and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
By moving it to
permit.All()it will work but it's not the case here.
This is where i handle the redirect inside @Controller
@GetMapping("/authority")
public String getAuth(HttpServletResponse response) {
if (jwt == null) {
return "redirect:/login";
}
if (jwtTokenUtil.isTokenExpired(jwt)) {
return "redirect:/login?token=expired";
}
response.addHeader("Auth", "Bearer " + jwt);
System.out.println(loggedinUser.getRoles());
if (loggedinUser != null) {
if (loggedinUser.getRoles().equalsIgnoreCase("TILEFONITIS")) {
return "redirect:/dashboard"; //will redirect
} else if (loggedinUser.getRoles().equalsIgnoreCase("ADMIN")) {
System.out.println("Admin");
return "redirect:/admin"; //won't redirect
} else if (loggedinUser.getRoles().equalsIgnoreCase("GUEST")) {
return "redirect:/403"; // will redirect
} else {
return "redirect:/dashboard"; // will redirect
}
} else {
return "redirect:/login";
}
}
and this is my /admin inside @Controller which is never called.
@GetMapping("/admin")
public String getAdmin(HttpServletResponse response) {
if (jwt == null) {
return "redirect:/login";
}
if (jwtTokenUtil.isTokenExpired(jwt)) {
return "redirect:/login?token=expired";
}
response.addHeader("Auth", "Bearer " + jwt);
System.out.println("jwt" + jwt);
return "admin";
}
The odd thing is that with Postman i get redirected!
What am i missing here?
Edit: The first call is at /authenticate/web where i tell spring i'm authenticated
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(auth.getUsername(), auth.getPassword()));
Edit 2:
To make things even clearer:
Visiting from web, flow:
- POST
/authenticate/web - redirect with
.jsto/authority(GET) - Won't redirect to
/admin(GET) -> 403
Visiting from Postman, flow:
- POST
/authenticate/web - Get the
JWTand include it in headers and make a GET to/authority - I'm seeing the admin template. -> 200
That's really odd, i add the jwt every time with response.addHeader on the web flow .
Update:
- These are the response headers from postman:
plus the JWT .
- Response headers from the web
Although now i noticed i get 302 from the web instead of a 200
and as you can see admin page is 403
Update 2:
I've managed to break down a few things, first of all
by having a
httpSecurity.addFilterBeforeon my security configuration means spring will look for theJWTand add a filter before the position of the specified filter classauthorities are correctly assigned to users, so there is no issue there
i changed
hasAuthority()tohasRole()
If you get the current user you can automatically access it's authority as shown below
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println("Principal: "+auth.getPrincipal());
System.out.println("Authorities: "+auth.getAuthorities());
Because the
authenticationis overriden by thejwt filterthis means i will only manage to get a user only if the request header contains the validjwt
this is why it worked from postman but not from the web.
Another issue is that in my controller i'm trying to add the jwt on the response header which will be added to it only when the controller finishes it's job, i can't get in the very next line the user principal becuase there is no jwt to it's request header.
This screenshot represents a web call and the call from postman where both access /authority endpoint.
- From postman you see
ADMINas an authority - But from the web i have a
ROLE_ANONYMOUS
So i have two options to solve this:
- Add it to the request header.
- Protect
RESTendpoints withJWTand use default spring security (hasRole()etc) for the web part.



