Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.
90
90%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Risky
Do not use without reviewing
JWT authentication and authorization patterns for Spring Boot 3.5.x using Spring Security 6.x and JJWT. Covers token generation, validation, refresh strategies, RBAC/ABAC, and OAuth2 integration.
This skill provides implementation patterns for stateless JWT authentication in Spring Boot applications. It covers the complete authentication flow including token generation with JJWT 0.12.6, Bearer/cookie-based authentication, refresh token rotation, and method-level authorization with @PreAuthorize expressions.
Key capabilities:
@PreAuthorize rulesActivate when user requests involve:
`@PreAuthorize`| Artifact | Scope |
|---|---|
spring-boot-starter-security | compile |
spring-boot-starter-oauth2-resource-server | compile |
io.jsonwebtoken:jjwt-api:0.12.6 | compile |
io.jsonwebtoken:jjwt-impl:0.12.6 | runtime |
io.jsonwebtoken:jjwt-jackson:0.12.6 | runtime |
spring-security-test | test |
See references/jwt-quick-reference.md for Maven and Gradle snippets.
| Property | Example Value | Notes |
|---|---|---|
jwt.secret | ${JWT_SECRET} | Min 256 bits, never hardcode |
jwt.access-token-expiration | 900000 | 15 min in milliseconds |
jwt.refresh-token-expiration | 604800000 | 7 days in milliseconds |
jwt.issuer | my-app | Validated on every token |
jwt.cookie-name | jwt-token | For cookie-based auth |
jwt.cookie-http-only | true | Always true in production |
jwt.cookie-secure | true | Always true with HTTPS |
| Annotation | Example |
|---|---|
@PreAuthorize("hasRole('ADMIN')") | Role check |
@PreAuthorize("hasAuthority('USER_READ')") | Permission check |
@PreAuthorize("hasPermission(#id, 'Doc', 'READ')") | Domain object check |
@PreAuthorize("@myService.canAccess(#id)") | Spring bean check |
Include spring-boot-starter-security, spring-boot-starter-oauth2-resource-server, and the three JJWT artifacts in your build file. See references/jwt-quick-reference.md for exact Maven/Gradle snippets.
jwt:
secret: ${JWT_SECRET:change-me-min-32-chars-in-production}
access-token-expiration: 900000
refresh-token-expiration: 604800000
issuer: my-app
cookie-name: jwt-token
cookie-http-only: true
cookie-secure: false # true in productionSee references/jwt-complete-configuration.md for the full properties reference.
Core operations: generate access token, generate refresh token, extract username, validate token.
@Service
public class JwtService {
public String generateAccessToken(UserDetails userDetails) {
return Jwts.builder()
.subject(userDetails.getUsername())
.issuer(issuer)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + accessTokenExpiration))
.claim("authorities", getAuthorities(userDetails))
.signWith(getSigningKey())
.compact();
}
public boolean isTokenValid(String token, UserDetails userDetails) {
try {
String username = extractUsername(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
} catch (JwtException e) {
return false;
}
}
}See references/jwt-complete-configuration.md for the complete JwtService including key management and claim extraction.
Extend OncePerRequestFilter to extract a JWT from the Authorization: Bearer header (or HttpOnly cookie), validate it, and set the SecurityContext.
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
String jwt = authHeader.substring(7);
String username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}See references/configuration.md for the cookie-based variant.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated()
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}See references/jwt-complete-configuration.md for CORS, logout handler, and OAuth2 login integration.
Expose /register, /authenticate, /refresh, and /logout via @RestController. Return accessToken + refreshToken in the response body (and optionally set an HttpOnly cookie).
See references/examples.md for the complete AuthenticationController and AuthenticationService.
Store refresh tokens in the database with user_id, expiry_date, revoked, and expired columns. On /refresh, verify the stored token, revoke it, and issue a new pair (token rotation).
See references/token-management.md for RefreshToken entity, rotation logic, and Redis-based blacklisting.
Use @EnableMethodSecurity and @PreAuthorize annotations for fine-grained control:
@PreAuthorize("hasRole('ADMIN')")
public Page<UserResponse> getAllUsers(Pageable pageable) { ... }
@PreAuthorize("hasPermission(#documentId, 'Document', 'READ')")
public Document getDocument(Long documentId) { ... }See references/authorization-patterns.md for RBAC entity model, PermissionEvaluator, and ABAC patterns.
@SpringBootTest
@AutoConfigureMockMvc
class AuthControllerTest {
@Test
void shouldDenyAccessWithoutToken() throws Exception {
mockMvc.perform(get("/api/orders"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(roles = "ADMIN")
void shouldAllowAdminAccess() throws Exception {
mockMvc.perform(get("/api/admin/users"))
.andExpect(status().isOk());
}
}See references/testing.md and references/jwt-testing-guide.md for full test suites, Testcontainers setup, and a security test checklist.
jti (JWT ID) claim for blacklisting on logoutAuthorization: Bearer header for mobile/API clientsSecure, SameSite=Lax or Strict on cookies in productionSecurityFilterChain bean — never extend WebSecurityConfigurerAdapter@EnableMethodSecurity instead of deprecated @EnableGlobalMethodSecurityiss and aud claims; reject tokens from untrusted issuersUserDetails with @Cacheable to avoid DB lookup on every request@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@PostMapping("/authenticate")
public ResponseEntity<AuthResponse> authenticate(
@RequestBody LoginRequest request) {
return ResponseEntity.ok(authService.authenticate(request));
}
@PostMapping("/refresh")
public ResponseEntity<AuthResponse> refresh(@RequestBody RefreshRequest request) {
return ResponseEntity.ok(authService.refreshToken(request.refreshToken()));
}
@PostMapping("/logout")
public ResponseEntity<Void> logout() {
authService.logout();
return ResponseEntity.ok().build();
}
}@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
@GetMapping("/users")
public ResponseEntity<List<UserResponse>> getAllUsers() {
return ResponseEntity.ok(adminService.getAllUsers());
}
}See references/examples.md for complete entity models and service implementations.
| File | Content |
|---|---|
| references/jwt-quick-reference.md | Dependencies, minimal service, common patterns |
| references/jwt-complete-configuration.md | Full config: properties, SecurityFilterChain, JwtService, OAuth2 RS |
| references/configuration.md | JWT config beans, CORS, CSRF, error handling, session options |
| references/examples.md | Complete application setup: controllers, services, entities |
| references/authorization-patterns.md | RBAC/ABAC entity model, PermissionEvaluator, SpEL expressions |
| references/token-management.md | Refresh token entity, rotation, blacklisting with Redis |
| references/testing.md | Unit and MockMvc tests, test utilities |
| references/jwt-testing-guide.md | Testcontainers, load testing, security test checklist |
| references/security-hardening.md | Security headers, HSTS, rate limiting, audit logging |
| references/performance-optimization.md | Caffeine cache config, async validation, connection pooling |
| references/oauth2-integration.md | Google/GitHub OAuth2 login, OAuth2UserService |
| references/microservices-security.md | Inter-service JWT propagation, resource server config |
| references/migration-spring-security-6x.md | Migration from Spring Security 5.x |
| references/troubleshooting.md | Common errors, debugging tips |
exp, iss, and aud claims before trusting the tokenWebSecurityConfigurerAdapter is removed — use SecurityFilterChain beans only@EnableGlobalMethodSecurity is deprecated — use @EnableMethodSecurityHttpSecurity configuration (no method chaining)WebSecurityConfigurerAdapter.order() replaced by @Order on @Configuration classesjti claim is required for token blacklisting to work correctlyspring-boot-dependency-injection — Constructor injection patterns used throughoutspring-boot-rest-api-standards — REST API security patterns and error handlingunit-test-security-authorization — Testing Spring Security configurationsspring-data-jpa — User entity and repository patternsspring-boot-actuator — Security monitoring and health endpointsdocs
plugins
developer-kit-ai
developer-kit-aws
agents
docs
skills
aws
aws-cli-beast
aws-cost-optimization
aws-drawio-architecture-diagrams
aws-sam-bootstrap
aws-cloudformation
aws-cloudformation-auto-scaling
aws-cloudformation-bedrock
aws-cloudformation-cloudfront
aws-cloudformation-cloudwatch
aws-cloudformation-dynamodb
aws-cloudformation-ec2
aws-cloudformation-ecs
aws-cloudformation-elasticache
references
aws-cloudformation-iam
references
aws-cloudformation-lambda
aws-cloudformation-rds
aws-cloudformation-s3
aws-cloudformation-security
aws-cloudformation-task-ecs-deploy-gh
aws-cloudformation-vpc
references
developer-kit-core
agents
commands
skills
developer-kit-devops
developer-kit-java
agents
commands
docs
skills
aws-lambda-java-integration
aws-rds-spring-boot-integration
aws-sdk-java-v2-bedrock
aws-sdk-java-v2-core
aws-sdk-java-v2-dynamodb
aws-sdk-java-v2-kms
aws-sdk-java-v2-lambda
aws-sdk-java-v2-messaging
aws-sdk-java-v2-rds
aws-sdk-java-v2-s3
aws-sdk-java-v2-secrets-manager
clean-architecture
graalvm-native-image
langchain4j-ai-services-patterns
references
langchain4j-mcp-server-patterns
references
langchain4j-rag-implementation-patterns
references
langchain4j-spring-boot-integration
langchain4j-testing-strategies
langchain4j-tool-function-calling-patterns
langchain4j-vector-stores-configuration
references
qdrant
references
spring-ai-mcp-server-patterns
spring-boot-actuator
spring-boot-cache
spring-boot-crud-patterns
spring-boot-dependency-injection
spring-boot-event-driven-patterns
spring-boot-openapi-documentation
spring-boot-project-creator
spring-boot-resilience4j
spring-boot-rest-api-standards
spring-boot-saga-pattern
spring-boot-security-jwt
assets
references
scripts
spring-boot-test-patterns
spring-data-jpa
references
spring-data-neo4j
references
unit-test-application-events
unit-test-bean-validation
unit-test-boundary-conditions
unit-test-caching
unit-test-config-properties
references
unit-test-controller-layer
unit-test-exception-handler
references
unit-test-json-serialization
unit-test-mapper-converter
references
unit-test-parameterized
unit-test-scheduled-async
references
unit-test-service-layer
references
unit-test-utility-methods
unit-test-wiremock-rest-api
references
developer-kit-php
developer-kit-project-management
developer-kit-python
developer-kit-specs
commands
docs
hooks
test-templates
tests
skills
developer-kit-tools
developer-kit-typescript
agents
docs
hooks
rules
skills
aws-cdk
aws-lambda-typescript-integration
better-auth
clean-architecture
drizzle-orm-patterns
dynamodb-toolbox-patterns
references
nestjs
nestjs-best-practices
nestjs-code-review
nestjs-drizzle-crud-generator
nextjs-app-router
nextjs-authentication
nextjs-code-review
nextjs-data-fetching
nextjs-deployment
nextjs-performance
nx-monorepo
react-code-review
react-patterns
shadcn-ui
tailwind-css-patterns
tailwind-design-system
references
turborepo-monorepo
typescript-docs
typescript-security-review
zod-validation-utilities
references
github-spec-kit