"I am relatively new to Java and Spring boot applications, I am trying to follow a YouTube tutorial.
I have created the signup and login endpoints and testing using postman, and signup works and the details are being created in database with encrypted password. When I try to use the same credentials to test the login endpoint. I am getting a 403 request forbidden error. I placed a debugger in the spring security."
"Below is the code for my JWTauthenticationFilter":
```@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JWTUtil jwtUtil;
private final UserService userService;
@Override
protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest,
@NonNull HttpServletResponse httpServletResponse,
@NonNull FilterChain filterChain) throws ServletException, IOException {
final String authHeader = httpServletRequest.getHeader("Authorization");
final String jwt;
final String userEmail;
if(StringUtils.isEmpty(authHeader) || !StringUtils.startsWith(authHeader, "Bearer ")) {
filterChain.doFilter(httpServletRequest, httpServletResponse);
return;
}
jwt = authHeader.substring(7);
userEmail = jwtUtil.extractUserName(jwt);
if(StringUtils.isNoneEmpty(userEmail)
&& SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = userService.userDetailsService().loadUserByUsername(userEmail);
if(jwtUtil.isTokenValid(jwt, userDetails)){
SecurityContext context = SecurityContextHolder.createEmptyContext();
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
context.setAuthentication(authToken);
SecurityContextHolder.setContext(context);
}
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}```
Below is the code for my WebSecurityConfiguration:
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class WebSecurityConfiguration {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final UserService userService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(request ->
request.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasAnyAuthority(UserRole.ADMIN.name())
.requestMatchers("/api/customer/**").hasAnyAuthority(UserRole.CUSTOMER.name())
.anyRequest().authenticated()).sessionManagement(manger ->
manger.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProviders())
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProviders() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService.userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}```
</code></pre>
I tried using webresources and different GPTs and there seems to be no clarity with what is going on...
I did exactly as I was shown in the tutorial.
And the below is the console : I hope someone figures it out, I have tried extensively looking for a solution...
<pre><code>
```2024-03-21T14:58:27.212-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.security.web.FilterChainProxy : Securing POST /api/auth/login </code>`
<code>2024-03-21T14:58:27.213-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext</code>
<code>2024-03-21T14:58:27.213-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.security.web.FilterChainProxy : Secured POST /api/auth/login</code>
<code>2024-03-21T14:58:27.317-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.s.a.dao.DaoAuthenticationProvider : Failed to authenticate since user account is locked</code>
<code>2024-03-21T14:58:27.320-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access</code>
<code>2024-03-21T14:58:27.325-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.security.web.FilterChainProxy : Securing POST /error</code>
<code>2024-03-21T14:58:27.325-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext</code>
<code>2024-03-21T14:58:27.327-04:00 DEBUG 14564 --- [nio-9000-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access</code>
<code>2024-03-21T15:54:37.576-04:00 INFO 14564 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'```
</code></pre>
I was able to find the answer to my question above through an auth tutorial,
When the User class implements UserDetails, getAuthorities() method is overridden.
The "ROLE_" string needs to be passed to the method along with passing a user role. Below is the method...
@Override public Collection<? extends GrantedAuthority> getAuthorities() { return List.of(new SimpleGrantedAuthority("ROLE_" +userRole.name())); }