-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should we store JWT secret keys in Base64? #8165
Comments
JJWT has no requirements on how you store your keys. You're free to store and obtain your key bytes however you wish. JJWT actually prefers that you use With regards to your question about the secret bytes: It boils down to security (entropy specifically) and clarity:
So while JJWT doesn't require any particular byte array format - it just checks that the byte array length minimums are met per the JWT RFC specification's length requirements - secure-random is always the safest bet and a best practice if you're generating secrets as a convenience to others. Do with that as you will :) Finally, if you want to generate secure-random keys that are appropriate for a given algorithm that adheres to the tenets covered here, you can use JJWT's If you want to represent that securely-generated key in a String form: SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //or HS384 or HS512
String base64Key = Encoders.BASE64.encode(key.getEncoded());
// Note that base64Key is just encoded - not encrypted - so it's still not safe to share with others Anyway, I hope that helps! |
Thank you so much @lhazlewood - yes, that definitely helps, and this ticket is for sure going to be helpful for a lot of people, as I'm sure we'll have lots of questions about this. So, if I understand well, encoding the String in Base64 allows to store more secure keys. Of course, users need to generate that secure key correctly, and I'm not sure everyone will worry about this, but at least we will support this and document this, so we're doing our best! As a result, I'm closing this, and we'll keep the Base64 encoding for the secret key. Thanks again! |
I'd say that's generally correct. Just remember (or document?) that the Base64 text value is still considered a secret value (since encoding != encryption) and should never be visible by unintended parties. Happy to help! |
Oh yes @lhazlewood that should already be good everywhere in our documentation. The only downside is that now you can't read the value anymore (as it's in Base64) so we can't give hints like we used to do here. |
Ah, I see. Yeah, you'd have to have a comment to the right of the line or above it. Got it. |
@jdubois but IMO its not nice to do a breaking change for users in a minor release. May be we can find a way for existing apps that upgrade to work with string keys as well |
@deepu105 OK I got an idea during the night:
Then, for JHipster 6, we could drop the old "secret". Having the new key called "base64Secret" isn't bad, as it shows you need to encode your data. @deepu105 WDYT? |
@jdubois that sounds perfect. Lets do it |
OK I'm on it, should be done today. |
@jdubois : do we need to apply the changes to the JHipster Registry too ? |
@pascalgrimaud yes of course |
@pascalgrimaud I'll do it |
I'm realizing that if you have a microservice architecture, with a mix of older and newer JHipster applications, you cannot mix base64 en clear text secrets with the current config. What needs to be done is have the clear text secret have a higher priority than the base64 one: that way older and newer applications can work together. Not the best thing for security, but I've put some big warning log if you don't use base64 encoding, so that should be enough. And we'll migrate totally in JHipster 6. |
@jdubois :
For example, for the jhipster-sample-app-gateway project:
Tell me if I'm wrong ? |
@pascalgrimaud oh yes, I forgot to update the keys of the sample applications! I'll do it right now. |
It will impact users who use microservices application and want to upgrade. But it is mentionned in our patch notes, so it's OK for me. |
For microservices, if you have a mix of older and newer versions, you should use the old "secret" key property: it will work with all versions. However, it needs to be long enough. In the long term, the idea is to have "base64-secret" everywhere, but I didn't do it yet as indeed that would block people who don't upgrade all their microservices at once. |
Ensures the length of the secret is at least 512 bit long https://www.rfc-editor.org/rfc/rfc7518#page-7 https://javadoc.io/doc/com.auth0/java-jwt/latest/com/auth0/jwt/algorithms/Algorithm.html#HMAC512 We should follow the rule and give a 512 bit key by default and provide validation based on the same rule. jleroux: based on recommendation by Les Hazlewood (JJWT founder, Apache Shiro founder): jhipster/generator-jhipster#8165 (comment) I used a 512 bits key I created using https://www.allkeysgenerator.com (Encryption key mode). But I got this error: EntitySaxReader |E| Fatal Error reading XML on line 23, column 155 org.xml.sax.SAXParseException: The reference to entity "F" must end with the ';' delimiter. It was due to SSOJWTDemoData content. So I removed security.token.key from this file and used only the property in security.properties. Thanks: Ayan Farooqui for report and suggestion
Ensures the length of the secret is at least 512 bit long https://www.rfc-editor.org/rfc/rfc7518#page-7 https://javadoc.io/doc/com.auth0/java-jwt/latest/com/auth0/jwt/algorithms/Algorithm.html#HMAC512 We should follow the rule and give a 512 bit key by default and provide validation based on the same rule. jleroux: based on recommendation by Les Hazlewood (JJWT founder, Apache Shiro founder): jhipster/generator-jhipster#8165 (comment) I used a 512 bits key I created using https://www.allkeysgenerator.com (Encryption key mode). But I got this error: EntitySaxReader |E| Fatal Error reading XML on line 23, column 155 org.xml.sax.SAXParseException: The reference to entity "F" must end with the ';' delimiter. It was due to SSOJWTDemoData content. So I removed security.token.key from this file and used only the property in security.properties. Thanks: Ayan Farooqui for report and suggestion
Please note this is for the master branch: this comes from an upgrade to JJWT 0.10.5, which pushes us to store secret keys in Base64. This is not what we have in our latest release (v5.2.1), and would therefore be a breaking change if we do this.
This question is mostly for @mraible as he works with the people from JJWT ( @lhazlewood I think?), and hopefully he can have a correct answer.
So here is our current code on the master branch:
Besides being a breaking change, I don't get why this key should be encoded in Base64. Why couldn't we just store the secret key as a String, and read it as a byte array using:
I find this code mode simpler for us, but also the configuration would be much easier for our users. As this doesn't seem to be the approach recommended by JJWT, is there any reason to use a Base64-encoded String?
The text was updated successfully, but these errors were encountered: