Problem:
I am trying to create a Spring-based web server with role-based authentication, but I consistently receive a 403 Forbidden error. I have implemented a custom UserDetails
class, and I suspect there might be an issue with my configuration.
Code:
Custom UserDetails
:
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private final User user;
public CustomUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream().map(r -> new SimpleGrantedAuthority("ROLE_" + r.getName())).toList();
}
// ... other UserDetails methods
}
SecurityFilterChain
implementation:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(requests -> requests
.requestMatchers("/api/**").permitAll()
.requestMatchers("/secret/**").hasAuthority("USER")
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.addFilterBefore(authorizeFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
I've implemented a custom UserDetails
class and configured Spring Security for role-based authentication. However, I keep encountering a 403 Forbidden error, even though I believe the roles are correctly assigned. I've tried using both hasRole
and hasAuthority
, but the issue persists. What am I missing in my configuration?
Any insights or suggestions would be greatly appreciated. Thank you!
For resource servers with JWTs, authorities are set by the authentication converter.
The default authentication converter is JwtAuthenticarionConverter
, which delegates authorities convertion to a configurable authorities converter (the default uses the entries in scope
claim adding SCOPE_
prefix).
You can provide a JwtAuthenticationConverter
configured with another authorities converter (one using another claim as source for authorities), or switch to a completely different Converter<Jwt,? extends AbstractAuthenticationToken>
by using http.oauth2ResourceServer(oauth2-> oauth2.jwt(Jwt -> jwt.jwtAuthenticationConverter(...))
You might also consider this additional starter I maintain which uses an authorities converter configurable with just application properties (unless you provide your own authorities or authentication converter in your conf)