2

I am generating a public/private key pair which i will use for digital signature of a JWT with jose4j. Its working fine creating and validating the token as well. But once i restart the server, then the previously issued tokens become invalid. I feel that everytime i restart the server it creates the new key. This is how i generate key inside the constructor:

    rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
    // Give the JWK a Key ID (kid), which is just the polite thing to do
    rsaJsonWebKey.setKeyId("secretKey");

It also happens when we try to create new instance of class. It says the token is invalid.

Any help would be appreciated. Thanks..

Shubham Jain
  • 56
  • 1
  • 5

1 Answers1

4

Each call to RsaJwkGenerator.generateJwk(...) generates a new public/private key pair. A signature on a JWT that's signed with a private key can only be verified with the corresponding public key (that's a big piece of the security). Bottom line is that the appropriate key needs to be used for the given context and that suggests a different way of accessing the key in your application.

So for different instances of some class needing the same key, some kind of singleton for the key might be appropriate.

To survive application restarts, the key needs to be persisted and loaded somehow. Using java's Keystore is one way you could do that. Or the whole JWK's JSON can be accessed as a String with rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE) and saved somewhere. You do want to be careful with the private key though so save it somewhere secure and/or maybe you could encrypt the whole thing with a JWE - a little code for some of that using password based encryption is shown here:

    String jwkjson = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);
    JsonWebEncryption encryptingJwe = new JsonWebEncryption();
    encryptingJwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.PBES2_HS256_A128KW);
    encryptingJwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
    encryptingJwe.setKey(new PbkdfKey("some decent passphrase/password here"));
    encryptingJwe.setPayload(jwkjson);
    String jweEncryptedJwk = encryptingJwe.getCompactSerialization();

    // save  jweEncryptedJwk somewhere  and load it on application start 

    JsonWebEncryption decryptingJwe = new JsonWebEncryption();
    decryptingJwe.setCompactSerialization(jweEncryptedJwk);
    encryptingJwe.setKey(new PbkdfKey("some decent passphrase/password here"));
    String payload = encryptingJwe.getPayload();
    PublicJsonWebKey publicJsonWebKey = PublicJsonWebKey.Factory.newPublicJwk(payload);
    // share the public part with whomever/whatever needs to verify the signatures 
    System.out.println(publicJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY));
Brian Campbell
  • 2,293
  • 12
  • 13