Goal

This article describes how to use public/private keys to create and verify Json Web Token (JWT) with java.

Used technologies

JDK 1.8
Maven 3.2
Maven dependencies: io.jsonwebtoken 0.7.0 + junit

Maven dependencies

  <dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.7.0</version>
	</dependency>
	<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
	</dependency>	

Test class


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.Date;

import org.junit.Test;

public class JwtRsaTest {
	
	@Test
	public void testJWTWithRsa() throws NoSuchAlgorithmException {
		KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
		keyGenerator.initialize(1024);

		KeyPair kp = keyGenerator.genKeyPair();
		PublicKey publicKey = (PublicKey) kp.getPublic();
		PrivateKey privateKey = (PrivateKey) kp.getPrivate();

		String encodedPublicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded());
		System.out.println("Public Key:");
		System.out.println(convertToPublicKey(encodedPublicKey));
		String token = generateJwtToken(privateKey);
		System.out.println("TOKEN:");
		System.out.println(token);
		printStructure(token, publicKey);
	}

	@SuppressWarnings("deprecation")
	public String generateJwtToken(PrivateKey privateKey) {
		String token = Jwts.builder().setSubject("adam")
				.setExpiration(new Date(2018, 1, 1))
				.setIssuer("info@wstutorial.com")
				.claim("groups", new String[] { "user", "admin" })
				// RS256 with privateKey
				.signWith(SignatureAlgorithm.RS256, privateKey).compact();
		return token;
	}

	//Print structure of JWT
	public void printStructure(String token, PublicKey publicKey) {
		Jws parseClaimsJws = Jwts.parser().setSigningKey(publicKey)
				.parseClaimsJws(token);

		System.out.println("Header     : " + parseClaimsJws.getHeader());
		System.out.println("Body       : " + parseClaimsJws.getBody());
		System.out.println("Signature  : " + parseClaimsJws.getSignature());
	}

	
	// Add BEGIN and END comments
	private String convertToPublicKey(String key){
		StringBuilder result = new StringBuilder();
		result.append("-----BEGIN PUBLIC KEY-----\n");
		result.append(key);
		result.append("\n-----END PUBLIC KEY-----");
		return result.toString();
	}
}

Result

Public Key:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCKXsBGx7l8ze1Dqlbgt3sFPYgBBWg4lwDb5KbB1KBvQB0mMZIu/9qZUToFyztbYZCJ7Utb9bYfvkDsVDa9Bqn4zkoSJUDQqac2uRHo3Up4WFMzhT2EB1iKZRYAteBG7Dr+i0e/kPes+3uentGPnBeQHGfZCgzAG1cYNoxB/PJ7uwIDAQAB
-----END PUBLIC KEY-----
TOKEN:
eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZGFtIiwiZXhwIjo2MTQ3NTU4MzYwMCwiaXNzIjoiaW5mb0B3c3R1dG9yaWFsLmNvbSIsImdyb3VwcyI6WyJ1c2VyIiwiYWRtaW4iXX0.cLqjW9OMu2EkVxUvu-6ildk2oq4HlSbriZJvJ9K1Ey2y7GGQfWpw3ZdlM-g8QJrRKBHCVMWeWC9pEVSKwQX1QipovSNRdvSriVvlfZfWa48Z_BsvzQxN_V_xcMdnQ0J0UN3WELb5uE5Y6Ntlqtj_4gRM3JUFf_wnslsyWCFUrg0
Header     : {alg=RS256}
Body       : {sub=adam, exp=61475583600, iss=info@wstutorial.com, groups=[user, admin]}
Signature  : cLqjW9OMu2EkVxUvu-6ildk2oq4HlSbriZJvJ9K1Ey2y7GGQfWpw3ZdlM-g8QJrRKBHCVMWeWC9pEVSKwQX1QipovSNRdvSriVvlfZfWa48Z_BsvzQxN_V_xcMdnQ0J0UN3WELb5uE5Y6Ntlqtj_4gRM3JUFf_wnslsyWCFUrg0

Jwt IO debugger

Visit Json Web Token, in debugger change Algorithm to RS256. Paste token in "Encoded" Input.
For the first time the validation Balk (See Bottom) will be red, now paste public key (---BEGIN....) in the first textarea under "VERIFY SIGNATURE"
Voila the Signature is now valid

References

  • Oracle Security Tutorial
  • Json Web Token
  • JJWT Github Repo