I want to achieve the following with Spring security:
User logs in via login.jsp
page and receives a JWT access token which is being stored as a cookie. After that he get redirected to secure.jsp
where he can see his own username (this URL is secured). I'm using a filter to perform the authentication:
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getCookies() == null) {
filterChain.doFilter(request, response);
return;
}
Cookie cookie = null;
String token = null;
for (Cookie current : request.getCookies()) {
if (current.getName().equals("_jwt")) {
cookie = current;
token = cookie.getValue();
break;
}
}
if(token == null) {
filterChain.doFilter(request, response);
return;
}
if(tokenService.validateAccessToken(token)) {
UserDetails user = tokenService.extractUserDetails(token);
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities()));
}
filterChain.doFilter(request, response);
}
}
The security config class:
@Configuration
public class SecurityConfiguration {
public static final String[] PUBLIC_URLS = {
"/login",
"/register",
};
// Other beans...
@Bean
@SneakyThrows
public SecurityFilterChain filterChain(HttpSecurity http){
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(sess -> sess.sessionCreationPolicy(STATELESS))
.cors(cors -> Customizer.withDefaults())
.authorizeHttpRequests(requests -> requests
.requestMatchers(PUBLIC_URLS).permitAll()
.anyRequest().authenticated())
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class)
.build();
}
}
Furthermore I have server.servlet.context-path=/Muzej
in my application.properties.
My problem: even if my PUBLIC_URLS
starts with /Muzej
or not I get 403 error when I try to access my login page in the browser. I enabled debug logging and I got the following:
2024-06-02T12:19:59.187+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /login
2024-06-02T12:19:59.188+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2024-06-02T12:19:59.190+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Secured GET /login
2024-06-02T12:19:59.201+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /index.jsp
2024-06-02T12:19:59.207+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access
2024-06-02T12:19:59.211+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.security.web.FilterChainProxy : Securing GET /error
2024-06-02T12:19:59.212+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2024-06-02T12:19:59.213+02:00 DEBUG 26576 --- [VirtuelniVodic] [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access
However when I change PUBLIC_URLS
to ** it loads properly. So the problem is definietly with the Antmatchers in the config, but I just can't figure it out why. Any suggestion would be appreciated.
After some debugging I found out that I had to open the respective jsp
URL-s as well. Here is how I solved it:
public static final String[] PUBLIC_URLS = {
"/login",
"/register",
"/logout",
"/index.jsp",
"/login.jsp",
"/register.jsp",
"/error.jsp"
};