Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.
82
82%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Risky
Do not use without reviewing
Quick reference for common JWT patterns in Spring Boot 3.5.x applications.
<!-- Maven -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>// Gradle
implementation("io.jsonwebtoken:jjwt-api:0.12.6")
implementation("io.jsonwebtoken:jjwt-impl:0.12.6")
implementation("io.jsonwebtoken:jjwt-jackson:0.12.6")@Service
public class JwtService {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
public String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256)
.compact();
}
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public boolean isTokenValid(String token, UserDetails userDetails) {
String username = extractUsername(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody();
return claimsResolver.apply(claims);
}
}@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService());
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
String token = authHeader.substring(7);
String username = jwtService.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(token, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthenticationController {
private final AuthenticationService service;
@PostMapping("/register")
public ResponseEntity<AuthenticationResponse> register(@RequestBody RegisterRequest request) {
return ResponseEntity.ok(service.register(request));
}
@PostMapping("/authenticate")
public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody AuthenticationRequest request) {
return ResponseEntity.ok(service.authenticate(request));
}
@PostMapping("/refresh")
public ResponseEntity<AuthenticationResponse> refresh(@RequestBody RefreshRequest request) {
return ResponseEntity.ok(service.refresh(request));
}
@PostMapping("/logout")
public ResponseEntity<Void> logout(@RequestBody LogoutRequest request) {
service.logout(request);
return ResponseEntity.ok().build();
}
}# application.yml
jwt:
secret: ${JWT_SECRET:your-256-bit-secret-key-here-at-least-32-characters}
access-token-expiration: 900000 # 15 minutes
refresh-token-expiration: 604800000 # 7 days
issuer: ${JWT_ISSUER:your-app-name}
cookie:
name: jwt-token
secure: ${JWT_COOKIE_SECURE:true} # true in production
http-only: true
same-site: strict
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${JWT_ISSUER_URI:https://your-auth-server.com}public String generateTokenWithClaims(UserDetails userDetails, Map<String, Object> claims) {
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.claim("roles", userDetails.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList()))
.signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS256)
.compact();
}public boolean isTokenValidWithSkew(String token, UserDetails userDetails) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.setAllowedClockSkewSeconds(60) // 1 minute tolerance
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException e) {
return false;
}
}public Claims extractAllClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody();
}// Generate secure key
SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
String base64Key = Encoders.BASE64.encode(key.getEncoded());// Short-lived access tokens (15 minutes)
long accessTokenExpiration = 15 * 60 * 1000; // 15 minutes
// Longer refresh tokens (7 days)
long refreshTokenExpiration = 7 * 24 * 60 * 60 * 1000; // 7 dayspublic boolean validateAllClaims(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
.requireIssuer("your-app-name")
.requireAudience("your-app-users")
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException e) {
return false;
}
}@Service
public class TokenBlacklistService {
private final Set<String> blacklistedTokens = ConcurrentHashMap.newKeySet();
public void blacklistToken(String token) {
blacklistedTokens.add(token);
}
public boolean isBlacklisted(String token) {
return blacklistedTokens.contains(token);
}
}@Test
void shouldGenerateValidToken() {
UserDetails userDetails = User.builder()
.username("test@example.com")
.password("password")
.authorities("ROLE_USER")
.build();
String token = jwtService.generateToken(userDetails);
assertThat(token).isNotNull();
assertThat(jwtService.extractUsername(token)).isEqualTo("test@example.com");
assertThat(jwtService.isTokenValid(token, userDetails)).isTrue();
}@SpringBootTest
@AutoConfigureMockMvc
class AuthenticationIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void shouldAuthenticateUser() throws Exception {
LoginRequest request = new LoginRequest("user@example.com", "password123");
mockMvc.perform(post("/api/auth/authenticate")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.accessToken").exists())
.andExpect(jsonPath("$.refreshToken").exists());
}
}@RestControllerAdvice
public class JwtExceptionHandler {
@ExceptionHandler(JwtException.class)
public ResponseEntity<ErrorResponse> handleJwtException(JwtException e) {
ErrorResponse error = new ErrorResponse(
"Invalid token",
e.getMessage(),
HttpStatus.UNAUTHORIZED.value()
);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
}
@ExceptionHandler(ExpiredJwtException.class)
public ResponseEntity<ErrorResponse> handleExpiredJwtException(ExpiredJwtException e) {
ErrorResponse error = new ErrorResponse(
"Token expired",
"The authentication token has expired",
HttpStatus.UNAUTHORIZED.value()
);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
}
}Error: The signing key's size is 184 bits which is not secure enough for the HS256 algorithm. Solution: Use a key of at least 256 bits (32 characters).
Error: JWT is expired or not yet valid Solution: Add clock skew tolerance.
Jwts.parserBuilder()
.setAllowedClockSkewSeconds(60)
.build()
.parseClaimsJws(token);Solution: Configure CORS properly.
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(List.of("http://localhost:*"));
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;
}plugins
developer-kit-ai
skills
chunking-strategy
prompt-engineering
developer-kit-aws
skills
aws
aws-cli-beast
aws-cost-optimization
aws-drawio-architecture-diagrams
aws-sam-bootstrap
aws-cloudformation
aws-cloudformation-auto-scaling
references
aws-cloudformation-bedrock
references
aws-cloudformation-cloudfront
references
aws-cloudformation-cloudwatch
references
aws-cloudformation-dynamodb
references
aws-cloudformation-ec2
aws-cloudformation-ecs
references
aws-cloudformation-elasticache
aws-cloudformation-iam
references
aws-cloudformation-lambda
references
aws-cloudformation-rds
aws-cloudformation-s3
references
aws-cloudformation-security
references
aws-cloudformation-task-ecs-deploy-gh
aws-cloudformation-vpc
developer-kit-core
skills
developer-kit-java
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
graalvm-native-image
langchain4j
langchain4j-mcp-server-patterns
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
references
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
unit-test-controller-layer
unit-test-exception-handler
unit-test-json-serialization
unit-test-mapper-converter
unit-test-parameterized
unit-test-scheduled-async
unit-test-service-layer
unit-test-utility-methods
unit-test-wiremock-rest-api
developer-kit-php
skills
aws-lambda-php-integration
developer-kit-python
skills
aws-lambda-python-integration
developer-kit-tools
developer-kit-typescript
skills
aws-lambda-typescript-integration
better-auth
drizzle-orm-patterns
dynamodb-toolbox-patterns
references
nestjs
nestjs-best-practices
nestjs-code-review
nestjs-drizzle-crud-generator
scripts
nextjs-app-router
nextjs-authentication
nextjs-code-review
nextjs-data-fetching
references
nextjs-deployment
nextjs-performance
nx-monorepo
react-code-review
react-patterns
references
shadcn-ui
tailwind-css-patterns
references
tailwind-design-system
references
turborepo-monorepo
typescript-docs
typescript-security-review
zod-validation-utilities