Back to home

Integrating Auth0 with Java Spring Boot

August 13, 20254 min read

Integrating Auth0 with Java Spring Boot

Authentication and authorization are critical components to my Boothmark project. In this blog post, we'll explore how to integrate Auth0 with Java 21 + Spring Boot to secure your APIs and applications.

Why Auth0?

Auth0 is a cloud-based authentication and authorization platform that provides a simple and secure way to add authentication and authorization to your Spring Boot applications. With Auth0, I don't have to worry about implementing and maintaining authentication and authorization logic myself. I can focus on building my application and let Auth0 handle the security.

Setting Up Your Spring Boot Application

Dependencies

First, add the required dependencies to your pom.xml:

XML
1
2
3
4
5
6
7
8
<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>

Configuration

Configure Auth0 in your application.yml:

YAML
1
2
3
4
5
6
7
8
9
10
auth0: domain: ${AUTH0_DOMAIN} audience: ${AUTH0_AUDIENCE} spring: security: oauth2: resourceserver: jwt: issuer-uri: https://${auth0.domain}/

Security Configuration

Create a comprehensive security configuration that defines which endpoints require authentication:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(auth -> auth .requestMatchers("/api/public/**").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())) ) .cors(withDefaults()) .csrf(csrf -> csrf.disable()) .build(); } // ... additional configuration }

This configuration:

  • Permits all requests to /api/public/**
  • Requires authentication for all other requests
  • Configures JWT token validation
  • Enables CORS for frontend integration
  • Disables CSRF for stateless APIs
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## Creating Protected Endpoints With authentication configured, you can now create controllers that automatically receive user information: @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/protected/profile") public ResponseEntity<Map<String, Object>> getProfile(@AuthenticationPrincipal Jwt jwt) { String userId = jwt.getSubject(); String email = jwt.getClaim("email"); String name = jwt.getClaim("name"); Map<String, Object> response = new HashMap<>(); response.put("userId", userId); response.put("email", email); response.put("name", name); return ResponseEntity.ok(response); } }

User Service Integration

Create a service to handle user data and integrate with your database:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Service public class UserService { @Transactional public User findOrCreateUser(String auth0Id, String email, String name) { User existingUser = userRepository.findByAuth0Id(auth0Id); if (existingUser != null) { // Update user info in case it changed in Auth0 existingUser.setEmail(email); existingUser.setName(name); return userRepository.save(existingUser); } // Create new user with default roles return createNewUser(auth0Id, email, name); } }

Authentication Helper Service

Create a utility service to extract user information from JWT tokens:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Service public class AuthService { public String getCurrentUserId(Authentication auth) { if (auth instanceof JwtAuthenticationToken jwt) { return jwt.getToken().getSubject(); } return null; } public String getCurrentUserEmail(Authentication auth) { if (auth instanceof JwtAuthenticationToken jwt) { return jwt.getToken().getClaim("email"); } return null; } }

Best Practices

1. Environment-Specific Configuration

Always use environment-specific configuration for sensitive information like Auth0 credentials. Avoid hardcoding them in your application.

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
spring: profiles: active: ${SPRING_PROFILES_ACTIVE:dev} --- spring: config: activate: on-profile: production security: oauth2: resourceserver: jwt: issuer-uri: ${AUTH0_ISSUER_URI}

2. CORS Configuration

Properly configure CORS for your frontend applications:

Java
1
2
3
4
5
6
7
8
9
10
11
12
@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(List.of("https://yourdomain.com")); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }

3. JWT Claims Validation

Configure additional JWT validation for enhanced security:

Java
1
2
3
4
5
6
7
8
9
@Bean public JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(jwt -> { // Extract and convert authorities from JWT claims return extractAuthorities(jwt); }); return converter; }

Testing Your Secured Endpoints

Spring Boot provides excellent testing support for secured endpoints:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
@WebMvcTest(UserController.class) class SecurityTests { @Autowired private MockMvc mvc; @Test @WithMockUser(roles = "USER") void testProtectedEndpoint() throws Exception { mvc.perform(get("/api/protected/profile")) .andExpect(status().isOk()); } }

Frontend Integration

Your frontend application will need to:

  1. Redirect users to Auth0 for authentication
  2. Receive the JWT token after successful authentication
  3. Include the token in API requests via the Authorization header:
JavaScript
1
2
3
4
5
6
7
const token = localStorage.getItem('access_token'); const response = await fetch('/api/protected/profile', { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } });

Conclusion

Integrating Auth0 with Spring Boot provides a robust, scalable solution for API security. The combination offers:

  • Simplified Authentication: Auth0 handles the complexity of user authentication
  • JWT-Based Security: Stateless authentication perfect for APIs
  • Flexible Authorization: Easy to implement role-based access control
  • Developer Experience: Spring Security's annotations make securing endpoints straightforward

This setup provides a solid foundation for building secure, modern web applications.

Remember to always follow security best practices, keep your dependencies up to date, and regularly review your security configuration as you application evolves.