Skip to main content

What is a JWT Token?

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. In this API, JWTs are used to securely transmit authentication information between the client and server.

Token Structure

A JWT consists of three parts separated by dots (.):
header.payload.signature

Example Token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJsaWJyYXJ5LWFwaSIsInN1YiI6ImpvaG5kb2UiLCJhdXRob3JpdGllcyI6IiIsImlhdCI6MTcwOTY0MDAwMCwiZXhwIjoxNzA5NjQxODAwLCJqdGkiOiIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwYWIiLCJuYmYiOjE3MDk2NDAwMDB9.signature

JWT Claims

The Library Management API includes the following claims in each JWT:
ClaimTypeDescriptionExample
issStringIssuer - identifies who issued the tokenConfigured via security.jwt.user.generator
subStringSubject - the username of the authenticated user"johndoe"
authoritiesStringComma-separated list of user authorities/roles"" (empty in current implementation)
iatNumberIssued At - timestamp when token was created1709640000
expNumberExpiration - timestamp when token expires1709641800
jtiStringJWT ID - unique identifier for the token"12345678-1234-1234-1234-1234567890ab"
nbfNumberNot Before - timestamp before which token is invalid1709640000
The exp (expiration) claim is set to 30 minutes (1800000 milliseconds) from the token creation time.

Token Generation

Tokens are generated during the login process using the JwtUtils.createToken() method:
public String createToken(Authentication authentication) {
    Algorithm algorithm = Algorithm.HMAC256(this.privateKey);
    
    String username = authentication.getPrincipal().toString();
    String authorities = authentication.getAuthorities()
            .stream()
            .map(grantedAuthority -> grantedAuthority.getAuthority())
            .collect(Collectors.joining(","));
    
    return JWT.create()
            .withIssuer(this.userGenerator)
            .withSubject(username)
            .withClaim("authorities", authorities)
            .withIssuedAt(new Date())
            .withExpiresAt(new Date(System.currentTimeMillis() + 1800000))
            .withJWTId(UUID.randomUUID().toString())
            .withNotBefore(new Date(System.currentTimeMillis()))
            .sign(algorithm);
}

Key Generation Details

1

Algorithm Selection

Uses HMAC256 (HS256) algorithm with a private key for signing
2

Extract User Information

Retrieves username and authorities from the Authentication object
3

Set Claims

Populates all required claims including issuer, subject, and timestamps
4

Calculate Expiration

Sets expiration to current time + 1,800,000 ms (30 minutes)
5

Generate Unique ID

Creates a UUID for the JWT ID (jti) claim
6

Sign Token

Signs the token using the HMAC256 algorithm with the private key

Token Validation

Every request to a protected endpoint must include a valid JWT token. The validation process is handled by the JwtTokenValidator filter:
@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response,
                                FilterChain filterChain) throws ServletException, IOException {
    
    String jwtToken = request.getHeader(HttpHeaders.AUTHORIZATION);
    
    if (jwtToken != null && jwtToken.startsWith("Bearer ")) {
        jwtToken = jwtToken.substring(7);
        
        DecodedJWT decodedJWT = jwtUtils.validationToken(jwtToken);
        String username = jwtUtils.extractUsername(decodedJWT);
        
        Authentication authentication = new UsernamePasswordAuthenticationToken(
            username, null, null);
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        context.setAuthentication(authentication);
        SecurityContextHolder.setContext(context);
    }
    
    filterChain.doFilter(request, response);
}

Validation Checks

The token validation process verifies:
  1. Signature Verification: Ensures the token hasn’t been tampered with
  2. Issuer Verification: Confirms the token was issued by this API
  3. Expiration Check: Validates the token hasn’t expired
  4. Format Validation: Ensures the token structure is valid
If validation fails, the request continues without authentication context, and Spring Security will return a 401 Unauthorized response for protected endpoints.

Using JWT Tokens in Requests

To access protected endpoints, include the JWT token in the Authorization header with the Bearer prefix:
curl -X GET "https://api.example.com/api/v1/books" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Token Extraction Methods

The JwtUtils class provides several methods to extract information from decoded tokens:
public String extractUsername(DecodedJWT decodedJWT) {
    return decodedJWT.getSubject().toString();
}

Token Expiration and Refresh

Expiration Time

  • Duration: 30 minutes (1800000 milliseconds)
  • Set at: Token creation time
  • Calculated as: current_time + 1800000

Handling Expiration

1

Client Detects Expiration

Client receives 401 Unauthorized response or proactively checks token expiration
2

Re-authenticate

Client must call the login endpoint again with user credentials
3

Receive New Token

API returns a new JWT token with updated expiration time
4

Update Stored Token

Client replaces old token with new token in storage
The API does not currently support token refresh without re-authentication. Users must provide their credentials again to obtain a new token.

Configuration Properties

The JWT system uses the following application properties:
PropertyDescriptionType
security.jwt.user.generatorIssuer identifier for JWT tokensString
security.jwt.key.privatePrivate key for HMAC256 signingString
These properties should be configured in application.properties or application.yml and kept secure, especially in production environments.

Security Best Practices

For API Developers

  • Keep the private key (security.jwt.key.private) secret and secure
  • Use environment variables for sensitive configuration
  • Never commit the private key to version control
  • Rotate keys periodically for enhanced security

For API Consumers

  • Store tokens securely (avoid localStorage for sensitive applications)
  • Never expose tokens in URLs or logs
  • Implement token refresh logic before expiration
  • Clear tokens on logout
  • Use HTTPS for all API communication

Common Token Errors

ErrorCauseSolution
Token signature verification failedToken was tampered with or signed with different keyObtain a new token through login
Token expiredToken age exceeds 30 minutesRe-authenticate to get a new token
Invalid issuerToken was not issued by this APIUse tokens only from this API
Malformed tokenToken format is incorrectEnsure token is properly formatted
Missing Authorization headerRequest doesn’t include the tokenAdd Authorization: Bearer <token> header

Login Process

Learn how to obtain JWT tokens through login

Registration

Create a new account to start using the API

Authentication Overview

Understand the complete authentication system

API Reference

View detailed authentication endpoint documentation

Build docs developers (and LLMs) love