Spring Security OAuth2 Resource Server Configuration
Spring Security OAuth2 provides a robust framework for securing REST APIs with token-based authentication. Therefore, understanding how to configure a resource server is essential for any modern Java backend. As a result, this guide walks you through the complete setup with production-ready patterns.
Understanding JWT Token Validation
JSON Web Tokens serve as the foundation for stateless authentication in resource server architectures. Moreover, JWTs carry claims that the server validates without contacting the authorization provider on every request. Specifically, the signature verification ensures token integrity.
The server decodes the token, verifies the signature against the issuer's public key, and checks expiration. Furthermore, custom claim validators can enforce additional business rules beyond standard JWT checks.
Resource server security configuration in a Java IDE
Configuring the Spring Security OAuth2 Filter Chain
Spring Boot simplifies resource server setup through auto-configuration and the starter dependency. Consequently, you only need a few properties and a security filter chain bean to get started. Additionally, the framework handles JWK set retrieval and caching automatically.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
.requestMatchers("/api/users/**").hasAuthority("SCOPE_read")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.decoder(jwtDecoder())
.jwtAuthenticationConverter(jwtAuthConverter())
)
);
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
NimbusJwtDecoder decoder = NimbusJwtDecoder
.withJwkSetUri("https://auth.example.com/.well-known/jwks.json")
.build();
decoder.setJwtValidator(tokenValidator());
return decoder;
}
private OAuth2TokenValidator<Jwt> tokenValidator() {
return new DelegatingOAuth2TokenValidator<>(
JwtValidators.createDefaultWithIssuer("https://auth.example.com"),
new JwtClaimValidator- >("aud",
aud -> aud.contains("my-api"))
);
}
@Bean
public JwtAuthenticationConverter jwtAuthConverter() {
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
converter.setAuthorityPrefix("SCOPE_");
converter.setAuthoritiesClaimName("permissions");
JwtAuthenticationConverter authConverter = new JwtAuthenticationConverter();
authConverter.setJwtGrantedAuthoritiesConverter(converter);
return authConverter;
}
}
This configuration establishes scope-based access control. Therefore, each endpoint requires specific scopes for authorization.
Scope-Based Authorization Patterns
Fine-grained authorization goes beyond simple authentication checks. However, you need a clear strategy for mapping scopes to application permissions. In contrast to role-based models, scope-based authorization ties permissions directly to the access token's granted scopes.
Method-level security annotations provide an additional layer of control. For example, the @PreAuthorize annotation enables expression-based access decisions on individual controller methods.
Scope-based authorization flow in a resource server
Custom JWT Decoder and Error Handling
Production deployments require custom error handling for expired or malformed tokens. Moreover, implementing a BearerTokenAuthenticationEntryPoint allows you to return structured error responses. Additionally, custom decoders can add audience validation and issuer checks beyond the defaults.
You should also configure token caching to reduce JWK set fetches. Specifically, the NimbusJwtDecoder caches keys by default, but you can tune the cache duration for high-throughput services.
Production-ready JWT validation with custom error handling
Related Reading:
Further Resources:
In conclusion, this framework enables stateless, scalable API protection with JWT validation. Therefore, adopt resource server configuration with scope authorization for robust security of your Spring Boot services.