JWT security in Spring Boot is powerful… but only when we separate responsibilities clearly. A Resource Server is not “the place where users log in”. It is the API that receives access tokens, validates them, extracts identity/permissions, and decides what the caller can access. ✅
🔸 TL;DR
Spring Boot can secure APIs as OAuth2 Resource Servers by validating JWTs, mapping claims to authorities, and applying authorization rules per endpoint.
🔸 1. PROTECTING AN API WITH TOKENS
A Resource Server is the backend API that protects business resources. It trusts an Authorization Server to issue tokens, then verifies incoming JWTs before processing requests.
GET /api/orders Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
The API does not authenticate the user with a password. It receives a Bearer token, validates it, then decides whether the request is allowed.
🔸 2. TURNING SPRING BOOT INTO A RESOURCE SERVER
Spring Security can validate JWTs automatically when the issuer or JWK Set URI is configured. Your API becomes responsible for checking token validity on each protected request.
☝️ A JWK Set URI is the URL where a Resource Server can fetch the public keys used to verify JWT signatures. (yaml property jwk-set-uri that can be used in place of issuer-uri)
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth.example.com/realms/demo
@Bean SecurityFilterChain security(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt()) .build(); }
Spring Boot uses the issuer metadata to validate JWT signature, expiration, and issuer. Every request must be authenticated unless you explicitly allow it.
🔸 3. ADAPTING JWT CLAIMS TO SPRING AUTHORITIES
JWTs often contain roles or permissions in custom claims. A converter lets you translate those claims into Spring Security authorities used by authorization rules.
☝️ hasRole - A shortcut for hasAuthority that prefixes ROLE_ or whatever is configured as the default prefix: https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
@Bean JwtAuthenticationConverter jwtAuthenticationConverter() { var authorities = new JwtGrantedAuthoritiesConverter(); authorities.setAuthoritiesClaimName("roles"); authorities.setAuthorityPrefix("ROLE_"); var converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(authorities); return converter; }
This maps a JWT claim like "roles": ["ADMIN"] to ROLE_ADMIN, making it usable with rules like hasRole("ADMIN").
🔸 4. SECURING ENDPOINTS BY INTENT
Once JWTs are validated and claims are mapped, endpoint rules define what each caller can do. Keep rules explicit, readable, and aligned with business intent.
@Bean
SecurityFilterChain security(
HttpSecurity http,
JwtAuthenticationConverter converter
) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/orders/**")
.hasAuthority("SCOPE_orders:read")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(converter))
)
.build();
}Public routes stay open, admin routes require a role, and order routes require a scope. The token is verified first, then authorization rules are applied.
🔸 TAKEAWAYS
▪️ A Resource Server protects APIs; it does not issue JWTs.
▪️ JWT validation should be handled by Spring Security, not custom manual parsing.
▪️ Claims are not automatically “business permissions”; sometimes they must be converted.
▪️ Authorization rules should express business access clearly.
▪️ Security config is not just technical plumbing — it documents who can do what.
JWTs are not magic. They become useful when validation, claim mapping, and authorization rules are designed together. 🔐
#Java #SpringBoot #SpringSecurity #OAuth2 #JWT #BackendDevelopment #APISecurity #SoftwareEngineering #CleanCode #JavaDeveloper
Go further with Java certification:
Java👇
Spring👇
SpringBook👇
JavaBook👇