I have started to work with JJWT to handle JWT on my server application.
My JWT secret will be stored at resources
folder and I will load the secret with Properties
class.
The JJWT provides three methods to sign the JWT, one uses byte[]
, other uses String
and the other uses Key
:
JwtBuilder signWith(SignatureAlgorithm var1, byte[] var2);
JwtBuilder signWith(SignatureAlgorithm var1, String var2);
JwtBuilder signWith(SignatureAlgorithm var1, Key var2);
The question: Regarding security, charset and other things, there are any recommendations of which one I should use?
For while, I stand with String
, since Properties
return a String
.
With JJWT >= 0.10.0,
signWith(SignatureAlgorithm var1, String var2)
has been deprecated because of the confusion between raw strings and Base64-encoded strings:This method expects the string argument to be a Base64-encoded secret key byte array. It does not assume a general string, like a user password for example, as the signing key. JJWT assumes Base64 encoding because if you're specifying a string password that is not Base64-encoded, you're probably using a poorly formed or weak key.
The JWT JWA specification REQUIRES that HMAC signing keys have lengths equal to or greater than the signature byte array length.
That means that:
Many online JWT sites and tools just just get this plain wrong - they allow you to think that you could type in or use any old string and you're good. Some go as far as even pre-populating the key with the word
secret
(clearly a bad idea and not even spec-compliant because it's too short!).To help simplify things for you, JJWT provides a utility to help you generate sufficient secure-random keys suitable for spec-compliant signing via the
io.jsonwebtoken.security.Keys
class'ssecretKeyFor
method. For example:If you wanted to store the generated key as a String, you could presumably Base64 encode it:
But note: the resulting
base64Key
string is not considered safe to show to anyone. Base64 encoding is not encryption - the value still needs to be kept secret. How you do this is up to you (encrypt it, etc).Now, when it is time to create a JWS, you could pass in that
base64Key
value, and JJWT knows to base64 decode it first to get the real bytes, which are then used to compute the signature:And while you could do this, it is not recommended per the above deprecation notice in the JavaDoc due to the ambiguity between raw strings and base64-encoded strings.
As a result, it is recommended to use either the JWT builder's
signWith(Key)
orsignWith(Key, SignatureAlgorithm)
methods which guarantee a type-safeKey
argument. For example:signWith(Key)
is recommended to let JJWT figure out the strongest algorithm possible based on the strength of your supplied key.signWith(Key,SignatureAlgorithm)
allows you to specify a desired algorithm if you don't want the strongest possible one.Both methods will reject any
Key
that doesn't meet the minimum RFC requirements.