java
45 lines · 8 steps
Configuring a JWT resource server in Spring
A stateless Spring Security config that validates JWTs by issuer and audience, then maps claims to roles and a principal.
Explained by
highlit
1@Configuration
2@EnableWebSecurity
3public class ResourceServerConfig {
4
5 @Value("${security.jwt.issuer-uri}")
6 private String issuerUri;
7
8 @Bean
9 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
10 http
11 .authorizeHttpRequests(auth -> auth
12 .requestMatchers(HttpMethod.GET, "/api/public/**").permitAll()
13 .requestMatchers("/api/admin/**").hasRole("ADMIN")
14 .anyRequest().authenticated())
15 .oauth2ResourceServer(oauth2 -> oauth2
16 .jwt(jwt -> jwt
17 .decoder(jwtDecoder())
18 .jwtAuthenticationConverter(jwtAuthenticationConverter())))
19 .sessionManagement(session -> session
20 .sessionCreationPolicy(SessionCreationPolicy.STATELESS));
21 return http.build();
22 }
23
24 @Bean
25 public JwtDecoder jwtDecoder() {
26 NimbusJwtDecoder decoder = JwtDecoders.fromIssuerLocation(issuerUri);
27 OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
28 OAuth2TokenValidator<Jwt> withAudience = new JwtClaimValidator<List<String>>(
29 "aud", aud -> aud != null && aud.contains("account-api"));
30 decoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(withIssuer, withAudience));
31 return decoder;
32 }
33
34 @Bean
35 public JwtAuthenticationConverter jwtAuthenticationConverter() {
36 JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter();
37 authoritiesConverter.setAuthoritiesClaimName("roles");
38 authoritiesConverter.setAuthorityPrefix("ROLE_");
39
40 JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
41 converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
42 converter.setPrincipalClaimName("preferred_username");
43 return converter;
44 }
45}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Resource servers verify incoming JWTs rather than issuing them, so no session or login form is needed.
- 2Layering token validators lets you enforce both issuer trust and audience scoping in one decoder.
- 3Claim converters translate a token's custom claims into Spring's roles and principal, bridging the identity provider to your app.
Related explainers
java
@Configuration @EnableBatchProcessing public class CustomerImportJobConfig {
How a chunk-based CSV import job works in Spring
batch-processing
etl
csv-parsing
Intermediate
9 steps
ruby
class TasksController < ApplicationController before_action :set_project def reorder
Bulk task reordering with upsert_all in Rails
bulk-update
upsert
authorization
Intermediate
8 steps
javascript
const express = require('express'); const jwt = require('jsonwebtoken'); const crypto = require('crypto');
Refresh token rotation in Express
jwt
token-rotation
authentication
Advanced
9 steps
java
@Configuration public class OrderConsumerConfig { @Bean
Wiring a resilient Kafka consumer in Spring
kafka
deserialization
error-handling
Intermediate
8 steps
java
@Configuration @EnableKafka public class KafkaErrorHandlingConfig {
Kafka retry and dead-letter handling in Spring
kafka
error-handling
retry
Intermediate
7 steps
java
@Controller @RequestMapping("/employees") public class EmployeeController {
Customizing form binding in a Spring MVC controller
data-binding
validation
type-conversion
Intermediate
9 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/configuring-a-jwt-resource-server-in-spring-explained-java-1cfd/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.