Creating a JWK
March 1, 2020
I wanted to create a JWK so that I could self-sign my JWT tokens during unit testing. The following code will generate a new JWK:
package com.drumcoder.diary.test.support.keygen; import java.util.UUID; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.jwk.KeyUse; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; /** * This program will generate a JWK key which can then be used for signing a JWT * during test code. * */ public class GenerateJwk { public static void main(String[] args) throws JOSEException { // Generate 2048-bit RSA key pair in JWK format, attach some metadata final RSAKey jwk = new RSAKeyGenerator(2048).keyUse(KeyUse.SIGNATURE) // indicate the intended use of the key .keyID(UUID.randomUUID().toString()) // give the key a unique ID .generate(); // Output the private and public RSA JWK parameters System.out.println(jwk); // Output the public RSA JWK parameters only System.out.println(jwk.toPublicJWK()); } }
I used the values generated from this code in two constants:
private static final String TEST_PRIVATE_KEY = "{\"p\":\"6PTEoZQWtYRlqQS7...\"}"; private static final String TEST_PUBLIC_KEY = "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"...}";
The following code can then be used to generate a bearer token:
private String createTestLoginAndCreateJwt(int expiryMinutes, List<String> roles, String username) throws MalformedURLException, IOException, ParseException, JOSEException { final RSAKey rsaJWK = this.fetchPublicKey("NoTenant", "TEST"); final RSAKey rsaPrivateJWK = RSAKey.parse(TEST_PRIVATE_KEY); // Create RSA-signer with the private key final JWSSigner signer = new RSASSASigner(rsaPrivateJWK); // Prepare JWT with claims set JSONArray claimsList = new JSONArray(); if (roles != null) { for (String role : roles) { claimsList.add(role); } } else { claimsList.add("DiaryUser"); } System.out.println(claimsList); final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject(username) .issuer("https://test.drumcoder.co.uk") .expirationTime(new Date(new Date().getTime() + (60 * 1000 * expiryMinutes))) .claim("roles", claimsList).build(); final SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(rsaJWK.getKeyID()).build(), claimsSet); // Compute the RSA signature signedJWT.sign(signer); // To serialize to compact form, produces something like // eyJhbGciOiJSUzI1NiJ9.SW4gUlNBIHdlIHRydXN0IQ.IRMQENi4nJyp4er2L... final String s = signedJWT.serialize(); System.out.println(s); return s; } private RSAKey fetchPublicKey(String tenantId, String kid) throws MalformedURLException, IOException, ParseException { return RSAKey.parse(TEST_PUBLIC_KEY); }
The JWT produced can be checked at http://jwt.io