A Springboot library that provides everything the standard Spring Security JWT Bearer authentication offers, with the added power of built-in DPoP (Demonstration of Proof-of-Possession) support for enhanced token security. Simplify your Auth0 JWT authentication integration for Spring Boot APIs with Auth0-specific configuration and validation.
This library builds on top of the standard Spring Security JWT authentication, providing:
- Complete Spring Security JWT Functionality - All features from Spring Security JWT Bearer are available
- Built-in DPoP Support - Industry-leading proof-of-possession token security per RFC 9449
- Auto-Configuration - Spring Boot auto-configuration with minimal setup
- Flexible Authentication Modes - Bearer-only, DPoP-only, or flexible mode supporting both
- Spring Boot 3.2+ (requires Java 17+) for Spring Boot integration
Add the dependency via Maven:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>auth0-springboot-api</artifactId>
<version>1.0.0-beta.0</version>
</dependency>or Gradle:
dependencies {
implementation 'com.auth0:auth0-springboot-api:1.0.0-beta.0'
}Add Auth0 authentication to your Spring Boot API:
1. Configure Auth0 properties in application.yml:
auth0:
domain: "your-tenant.auth0.com"
audience: "https://your-api-identifier"2. Create a Security Configuration class:
import com.auth0.spring.boot.Auth0AuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain apiSecurity(HttpSecurity http, Auth0AuthenticationFilter authFilter) throws Exception {
return http.csrf(csrf -> csrf.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/protected").authenticated()
.anyRequest().permitAll())
.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}3. Create your API endpoints:
@RestController
public class ApiController {
@GetMapping("/open-endpoint")
public ResponseEntity<String> openEndpoint() {
return ResponseEntity.ok("This endpoint is available to all users.");
}
@GetMapping("/api/protected")
public ResponseEntity<String> protectedEndpoint(Authentication authentication) {
String userId = authentication.getName();
return ResponseEntity.ok("Hello, authenticated user: " + userId);
}
}That's it! Your API now validates JWT tokens from Auth0.
Note - If authorization header is null for protected endpoints, WWW-Authenticate header in response is not added.
Required Settings:
- Domain: Your Auth0 domain (e.g.,
my-app.auth0.com) - without thehttps://prefix - Audience: The API identifier configured in your Auth0 Dashboard
Optional Settings:
auth0:
domain: "your-tenant.auth0.com"
audience: "https://your-api-identifier"
dpopMode: ALLOWED # DISABLED, ALLOWED (default), REQUIRED
dpopIatOffsetSeconds: 300 # 300 s (default)
dpopIatLeewaySeconds: 30 # 30s (default)DPoP (Demonstration of Proof-of-Possession) is a security mechanism that binds access tokens to a cryptographic key, making them resistant to token theft and replay attacks. This library provides seamless DPoP integration for your Auth0-protected APIs.
Learn more about DPoP: Auth0 DPoP Documentation
Enable DPoP by setting the mode in your configuration:
auth0:
domain: "your-tenant.auth0.com"
audience: "https://your-api-identifier"
dpopMode: ALLOWED # Enable DPoP support while maintaining Bearer token compatibilityThat's it! Your API now supports DPoP tokens while maintaining backward compatibility with Bearer tokens.
For fine-grained control, configure DPoP behavior:
auth0:
domain: "your-tenant.auth0.com"
audience: "https://your-api-identifier"
dpopMode: REQUIRED # Only accept DPoP tokens
dpopIatOffsetSeconds: 300 # Allow 300 seconds offset for 'iat' claim (default)
dpopIatLeewaySeconds: 30 # 30 seconds leeway for time-based validation (default)Choose the right enforcement mode for your security requirements:
| Mode | Description |
|---|---|
ALLOWED (default) |
Accept both DPoP and Bearer tokens |
REQUIRED |
Only accept DPoP tokens, reject Bearer tokens |
DISABLED |
Standard JWT Bearer validation only |
Example client requests:
Bearer Token (traditional):
curl -H "Authorization: Bearer <jwt_token>" \
https://your-api.example.com/api/protectedDPoP Token (enhanced security):
curl -H "Authorization: DPoP <jwt_token>" \
-H "DPoP: <dpop_proof>" \
https://your-api.example.com/api/protectedAccess JWT claims directly through Auth0AuthenticationToken's clean API:
@RestController
public class UserController {
@GetMapping("/api/user-profile")
public ResponseEntity<Map<String, Object>> userProfile(Authentication authentication) {
// Cast to Auth0AuthenticationToken to access Auth0-specific features
Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;
Map<String, Object> profile = new HashMap<>();
profile.put("userId", auth0Token.getClaim("sub"));
profile.put("email", auth0Token.getClaim("email"));
profile.put("scopes", auth0Token.getScopes()); // Set<String> of scopes
profile.put("authorities", authentication.getAuthorities()); // Spring Security authorities
return ResponseEntity.ok(profile);
}
@GetMapping("/api/admin")
public ResponseEntity<String> adminEndpoint(Authentication authentication) {
// Validate custom claims using individual claim access
Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;
String userRole = (String) auth0Token.getClaim("role");
if ("admin".equals(userRole)) {
return ResponseEntity.ok("Admin access granted");
} else {
return ResponseEntity.status(403).body("Admin role required");
}
}
}Implement scope-based access control:
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain apiSecurity(HttpSecurity http, Auth0AuthenticationFilter authFilter) throws Exception {
return http.csrf(csrf -> csrf.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/**").authenticated()
.requestMatchers("/api/users/**").hasAnyAuthority("SCOPE_read:messages")
.requestMatchers("/api/protected").authenticated()
.anyRequest().permitAll())
.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}For custom scope validation in controllers:
@Component
public class ScopeValidator {
public boolean hasRequiredScopes(Authentication authentication, String... requiredScopes) {
if (!(authentication instanceof Auth0AuthenticationToken)) {
return false;
}
Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;
Set<String> tokenScopes = auth0Token.getScopes();
return tokenScopes.containsAll(Arrays.asList(requiredScopes));
}
}
@RestController
public class AdminController {
@Autowired
private ScopeValidator scopeValidator;
@GetMapping("/api/admin")
public ResponseEntity<Map<String, Object>> adminEndpoint(Authentication authentication) {
if (!scopeValidator.hasRequiredScopes(authentication, "admin")) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(Map.of("error", "insufficient_scope"));
}
return ResponseEntity.ok(Map.of("message", "Admin access granted"));
}
}For comprehensive examples and use cases, see the playground application:
@RestController
public class ApiController {
@GetMapping("/open")
public String openEndpoint() {
return "This endpoint is available to all users.";
}
@GetMapping("/protected")
public String protectedEndpoint(Authentication auth) {
return "Hello, " + auth.getName() + "!";
}
}@GetMapping("/conditional")
public ResponseEntity<String> conditionalEndpoint(Authentication authentication) {
Auth0AuthenticationToken auth0Token = (Auth0AuthenticationToken) authentication;
String userRole = (String) auth0Token.getClaim("role");
if ("admin".equals(userRole)) {
return ResponseEntity.ok("Admin access granted");
} else {
return ResponseEntity.status(403).body("Admin access required");
}
}Clone the repository and build the project:
git clone https://github.com/auth0/auth0-auth-java.git
cd auth0-auth-java
./gradlew clean buildThe repository includes a playground application for testing both standard JWT Bearer and DPoP authentication:
-
Configure Auth0 settings in
auth0-springboot-api-playground/src/main/resources/application.yml:auth0: domain: "your-tenant.auth0.com" audience: "https://your-api-identifier" dpopMode: ALLOWED
-
Run the playground:
./gradlew :auth0-springboot-api-playground:bootRun
-
Access the application:
- Application:
http://localhost:8080 - Open endpoint: GET
/open-endpoint(no authentication required) - Protected endpoint: GET
/api/protected(requires authentication)
- Application:
1. Obtain a JWT token from Auth0:
curl -X POST https://your-tenant.auth0.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"audience": "https://your-api-identifier",
"grant_type": "client_credentials"
}'2. Test Bearer authentication:
curl -H "Authorization: Bearer <your-jwt-token>" \
http://localhost:8080/api/protected3. Test DPoP authentication (requires DPoP-bound token):
curl -H "Authorization: DPoP <your-dpop-bound-token>" \
-H "DPoP: <your-dpop-proof>" \
http://localhost:8080/api/protectedWe appreciate your contributions! Please review our contribution guidelines before submitting pull requests.
- Read the Auth0 General Contribution Guidelines
- Read the Auth0 Code of Conduct
- Ensure all tests pass
- Add tests for new functionality
- Update documentation as needed
- Sign all commits
If you have questions or need help:
- Check the Auth0 Documentation
- Visit the Auth0 Community
- Report issues on GitHub Issues
Copyright 2025 Okta, Inc. This project is licensed under the Apache License 2.0 - see the LICENSE file for details. Authors Okta Inc.

Auth0 is an easy-to-implement, adaptable authentication and authorization platform. To learn more check out Why Auth0?
This project is licensed under the Apache License 2.0. See the LICENSE file for more info.