A Resource Server is an application that serves protected resources and validates access tokens issued by an Authorization Server (like Keycloak, Okta, Auth0, or a custom Authorization Server).
🔑 Core Concepts
- Authorization Server → Issues tokens (JWT, opaque). Example: Keycloak, Auth0.
- Resource Server → Your Spring Boot REST API that checks tokens before serving data.
- Client → A frontend/mobile app that requests tokens from Authorization Server and calls the Resource Server.
🚀 Example: Spring Boot Resource Server
We’ll build a simple REST API (/api/hello
) protected with JWT validation.
1. Dependencies (pom.xml
)
Add Spring Boot starter + security + OAuth2 resource server:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-jose</artifactId>
</dependency>
</dependencies>
2. Configuration (application.yml
)
Here, we assume JWT tokens are issued by an Authorization Server (example: Keycloak):
server:
port: 8081
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth-server.com/realms/myrealm
issuer-uri
→ The endpoint where the Resource Server can fetch public keys (JWKS) to validate tokens.- Works with Keycloak, Okta, Auth0, etc.
3. Security Config (SecurityConfig.java
)
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@org.springframework.context.annotation.Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt()); // enable JWT validation
return http.build();
}
}
4. REST Controller (HelloController.java
)
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
@RestController
public class HelloController {
@GetMapping("/api/public")
public String publicEndpoint() {
return "This is a public endpoint 🚀";
}
@GetMapping("/api/hello")
public String hello(@AuthenticationPrincipal Jwt jwt) {
return "Hello, " + jwt.getClaim("preferred_username");
}
}
5. Running & Testing
- Run your Spring Boot app (
mvn spring-boot:run
). - Get a valid JWT token from your Authorization Server.
- Call your endpoint with token:
curl -H "Authorization: Bearer <access_token>" http://localhost:8081/api/hello
If the token is valid → ✅ returns "Hello, <username>"
.
If not → ❌ returns 401 Unauthorized
.
🏁 Summary
- You used Spring Security + Resource Server to protect APIs.
- Configured it to validate JWT tokens from an external Authorization Server.
- Created public and protected endpoints.