Generating and Verifying JWT with RSA in Java and Spring Boot

harakat

NABIL HARAKAT

Posted on November 1, 2023

Generating and Verifying JWT with RSA in Java and Spring Boot

Introduction
In the world of web applications and microservices, securing data and ensuring user authentication is a paramount concern. JSON Web Tokens (JWTs) have become a popular solution for achieving secure data transmission and authentication. In this article, we will explore how to generate and verify JWTs with RSA in a Java Spring Boot application.

Technology Stack
we'll be working with a specific technology stack to generate and verify JWTs using RSA in a Java Spring Boot application. It's important to understand the key components of our stack:

  • Java 17
  • Spring Boot 3.1.5
  • OpenSSL

What is a JSON Web Token (JWT)?
JSON Web Tokens, or JWTs, are compact, self-contained data structures that can be used to securely transmit information between parties. They consist of three parts: a header, a payload, and a signature. JWTs are widely used for authentication and data exchange due to their efficiency, scalability, and statelessness.

The Power of RSA
RSA (Rivest-Shamir-Adleman) is a widely used public key encryption algorithm. It operates using a pair of keys: a public key used for encryption and a private key used for decryption. RSA's asymmetric nature makes it perfect for securing JWTs, as it allows us to use the public key to validate data signed with the private key.

Generating a JWT with RSA
To generate a JWT with RSA in a Java Spring Boot application, you will need the following:
A public key for verifying the JWT signature.
A private key for signing the JWT.
A library such as Bouncy Castle to work with X.509 certificates.

Exemple to generate a Jwt
Here's a simplified code snippet demonstrating how to generate a JWT:

// Generate a JWT token
    public String createToken(@Nullable Map<String, String> data) throws UnrecoverableKeyException,
            IllegalArgumentException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
        // check inputs
        if (data == null) {
            throw new IllegalArgumentException("Data map is null");
        }
        // Validate inputs
        String subject = data.get("sub");
        if (subject == null || subject.isEmpty()) {
            throw new IllegalArgumentException("Subject is required");
        }

        // Generate random IDs for JWT and header
        String jwtId = UUID.randomUUID().toString();
        String kid = UUID.randomUUID().toString();

        // Calculate the expiration date
        Date validity = calculateExpirationDate();

        // Create a JWT with a set of claims
        Builder builder = JWT.create().withSubject(subject).withIssuer("iss").withAudience("aud").withJWTId(jwtId)
                .withIssuedAt(new Date()).withExpiresAt(validity);

        // Create an Algorithm with the private key
        Algorithm algorithm = Algorithm.RSA256(certService.loadRSAPrivateKey());

        // Create a JWS header with the X.509 certificate and algorithm
        Map<String, Object> headerClaims = Map.of("kid", kid);
        builder.withHeader(headerClaims);

        // Sign the JWT with the private key
        String token = builder.sign(algorithm);

        // Print the JWT token
        log.info("JWT Token: " + token);

        return token;

    }
Enter fullscreen mode Exit fullscreen mode
// Calculate the expiration date as 2 hours from the current time
private Date calculateExpirationDate() {
  LocalDateTime expirationDateTime = LocalDateTime.now().plusHours(2);
  return Date.from(expirationDateTime.toInstant(ZoneOffset.UTC));
}
Enter fullscreen mode Exit fullscreen mode

Verifying a JWT with RSA
Verifying a JWT involves validating the signature using a public key. Here's how to verify a JWT in Java Spring Boot:

public void verifyToken(Map<String, String> data) throws IllegalArgumentException, KeyStoreException,
    NoSuchAlgorithmException, CertificateException, IOException {
  // check inputs
  if (data == null) {
    throw new IllegalArgumentException("Data map is null");
  }
  // Validate inputs
  String subject = data.get("token");
  if (subject == null || subject.isEmpty()) {
    throw new IllegalArgumentException("Token is required");
  }
  // Define the algorithm and secret key used to sign the JWT
  Algorithm algorithm = Algorithm.RSA256(certService.loadRSAPublicKey());

  // Create a JWTVerifier with the expected algorithm and secret
  JWTVerifier verifier = JWT.require(algorithm).build();

  // Verify the JWT
  try {
    DecodedJWT decodedJWT = verifier.verify(data.get("token"));
    log.info("JWT is valid.");
    log.info("Subject: " + decodedJWT.getSubject());
    log.info("Issuer: " + decodedJWT.getIssuer());
    log.info("Expiration: " + decodedJWT.getExpiresAt());
  } catch (Exception e) {
    log.error("JWT verification failed: " + e.getMessage());
  }

}

Enter fullscreen mode Exit fullscreen mode

Security Considerations
When working with JWTs and RSA, there are some crucial security considerations:

  • Protect Your Keys: Ensure your private key is securely stored and never exposed.
  • Token Expiration: Use token expiration to limit the window of opportunity for an attacker.
  • Key Rotation: Periodically update your keys and manage key rotation.

Use Cases
JWTs with RSA are versatile and find use in various scenarios, including:

  • Authenticating users in web applications.
  • Securing APIs and microservices.
  • Implementing Single Sign-On (SSO) for multiple services.

Accessing the Source Code
You can access the source code, along with detailed comments and explanations, by visiting the following GitHub repository:

https://github.com/nabil-harakat/jwt-service

Conclusion
Using JWTs with RSA in a Java Spring Boot application can enhance your data security and authentication mechanisms. With the power of RSA encryption, you can be confident that your data is secure during transmission and that your users are who they claim to be. Implementing JWTs with RSA is a valuable step toward a more secure and trustworthy application.
Remember to manage your keys carefully, implement token expiration, and stay updated on best practices for using JWTs with RSA to ensure a secure and robust authentication system.

đź’– đź’Ş đź™… đźš©
harakat
NABIL HARAKAT

Posted on November 1, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related