JWT Authentication in Java

Loading

JWT (JSON Web Token) is a compact, URL-safe means of representing claims to be transferred between two parties. It is commonly used for authentication and authorization in modern web applications. Below is a detailed guide on implementing JWT Authentication in Java, including key concepts, libraries, and step-by-step examples.


1. Key Concepts

a. What is JWT?

  • A JWT is a JSON object that is encoded and signed.
  • It consists of three parts:
  1. Header: Contains metadata (e.g., algorithm used for signing).
  2. Payload: Contains claims (e.g., user ID, roles, expiration time).
  3. Signature: Ensures the token’s integrity.

b. Structure of a JWT

Header.Payload.Signature
  • Example:
  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

c. Use Cases

  • Authentication: Verify the identity of a user.
  • Authorization: Grant access to resources based on roles or permissions.
  • Information Exchange: Securely transmit information between parties.

2. JWT Libraries for Java

Several libraries can be used to create, parse, and validate JWTs in Java:

  • JJWT (Java JWT): A simple and easy-to-use library.
  • Nimbus JOSE + JWT: A comprehensive library for JWT and JOSE (JSON Object Signing and Encryption).
  • Auth0 Java JWT: A library provided by Auth0 for JWT handling.

3. Implementing JWT Authentication

a. Add Dependencies

Include the necessary dependencies in your pom.xml (for Maven) or build.gradle (for Gradle).

Maven (JJWT):
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
Gradle (JJWT):
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'

b. Create a JWT Utility Class

Create a utility class to handle JWT creation and validation.

Example:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtUtil {

    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private static final long EXPIRATION_TIME = 86400000; // 24 hours

    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SECRET_KEY)
                .compact();
    }

    public static Claims parseToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    public static boolean validateToken(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

c. Create a Login Endpoint

Create a REST endpoint to authenticate users and issue JWTs.

Example:
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/auth")
public class AuthResource {

    @POST
    @Path("/login")
    @Produces(MediaType.APPLICATION_JSON)
    public Response login(UserCredentials credentials) {
        // Authenticate user (e.g., check username and password)
        if ("admin".equals(credentials.getUsername()) && "password".equals(credentials.getPassword())) {
            String token = JwtUtil.generateToken(credentials.getUsername());
            return Response.ok().entity(new AuthResponse(token)).build();
        } else {
            return Response.status(Response.Status.UNAUTHORIZED).build();
        }
    }
}

d. Create a Protected Endpoint

Create a REST endpoint that requires a valid JWT for access.

Example:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;

@Path("/protected")
public class ProtectedResource {

    @GET
    public Response getProtectedResource(@Context HttpHeaders headers) {
        String authHeader = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring("Bearer ".length());
            if (JwtUtil.validateToken(token)) {
                return Response.ok().entity("Access granted").build();
            }
        }
        return Response.status(Response.Status.UNAUTHORIZED).build();
    }
}

4. JWT Claims

JWT claims are key-value pairs that provide information about the token. Common claims include:

  • sub (Subject): Identifies the subject of the token (e.g., user ID).
  • exp (Expiration Time): Specifies the token’s expiration time.
  • iat (Issued At): Specifies when the token was issued.
  • roles: Custom claim for user roles.
Example:
public static String generateToken(String username, List<String> roles) {
    return Jwts.builder()
            .setSubject(username)
            .claim("roles", roles)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(SECRET_KEY)
            .compact();
}

5. Best Practices

  • Use Strong Keys: Use a strong secret key for signing JWTs.
  • Set Expiration: Always set an expiration time for JWTs.
  • Validate Tokens: Validate tokens on every request.
  • Use HTTPS: Transmit JWTs over HTTPS to prevent interception.
  • Store Securely: Store JWTs securely on the client side (e.g., in HTTP-only cookies).

6. Example Use Cases

  • User Authentication: Verify user identity during login.
  • API Security: Secure RESTful APIs with JWT-based authentication.
  • Single Sign-On (SSO): Implement SSO across multiple applications.

Leave a Reply

Your email address will not be published. Required fields are marked *