-
Notifications
You must be signed in to change notification settings - Fork 376
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
JWK Common Parameters #520
Conversation
representing values from the IANA JSON Web Key Parameters Registry which are not specific to any key type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great so far. Left some comments, please do not take them as the truth just comments and my opinions and my opinions change daily :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added one big comment about the JWK initializer, automatically becomes a little messy when backwards compatibility needs to be preserved.
The tests are also failing for older Rubies because of the Hash#except
method is missing, the exclusion of the private parts needs to be done manually I guess.
Im really liking the improvements, super work! and apologies for my nitpicking:)
lib/jwt/jwk/ec.rb
Outdated
|
||
super(options) | ||
raise ArgumentError, 'keypair must be of type OpenSSL::PKey::EC' unless keypair.is_a?(Hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few suggestions for the initializer (the suggestion applies for all the different types).
- The
keypair
parameter could be renamed to something more describing. - The given OpenSSL object could be kept to avoid recreation from JWK parameters
- The ArgumentError could tell that the parameter also can be a Hash
- Transforming the keys to symbols is only needed when first parameter is a Hash.
one idea would be to handle the different variants of the first parameters in a case-block:
def initialize(keypair_or_params, params = nil, options = {})
params ||= {}
# For backwards compatibility when kid was a String
params = { kid: params } if params.is_a?(String)
key_params = case keypair_or_params
when OpenSSL::PKey::EC # Accept OpenSSL key as input
@keypair = keypair_or_params # Preserve the object to avoid recreation
parse_ec_key(keypair_or_params)
when Hash
keypair_or_params.transform_keys(&:to_sym)
else
raise ArgumentError, 'keypair_or_params must be of type OpenSSL::PKey::EC or Hash with key parameters'
end
params = params.transform_keys(&:to_sym)
check_jwk(keypair, params)
super(options, key_params.merge(params))
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion 2: What do you think, would an example for the usage without the OpenSSL object in the readme be valuable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think, would an example for the usage without the OpenSSL object in the readme be valuable?
Yes. In fact, the section Importing and exporting JSON Web Keys
should probably demonstrate this instead of converting an OpenSSL key as in the example above.
The
keypair
parameter could be renamed to something more describing.
I agree, though keypair_or_params
runs the risk of suggesting that you can specify everything from the first argument in the second, which is not the case (e.g. the first argument needs to be the one describing the kty
).
In some other places I think I have simply used key
, which could be an OpenSSL Key or a JSON Web Key.
The given OpenSSL object could be kept to avoid recreation from JWK parameters
I like this 👍
I am having a bit of a struggle with RuboCop. |
I think the reason is the runtime you are using. RuboCop is executed on Ruby 3.1 on the CI |
This is so great! Still that one RuboCop issue and we are good to go. |
There is one more feature I have been thinking about adding: When initializing a JWK with another JWK of the same type as This would allow stuff such as jwk1 = JWT::JWK.new(OpenSSL::PKey::RSA.new 2048)
jwk2 = JWT::JWK.new(OpenSSL::PKey::RSA.new 2048)
jwks = { keys: [jwk1, jwk2] } # Note: no explicit export
# Uses key accessor to find key with right `kid` and calls `initialize` and `keypair`
JWT.decode my_token, nil, true, jwks: jwks which is useful if the JWKS is not created as above but fetched from some URL, but I guess even more useful would be some JWKS handling, which is best handled in a future PR :) |
I like the suggestion. But maybe not in this PR. One tiny thing still related to this PR, a little note in the changelog would be great. |
We are happy with this, right? No more changes coming @bellebaum? |
Not in this PR. I think it should be possible to extend this in the future, given that options parameters are now separate from params. So I am ok with the current state being merged unless there are further suggestions |
Great. Was thinking we could make some plan for the 3.0 version of this gem to get rid of the older behaviour of the interfaces that clutter the code. |
Super work here, highly appreciated. Also the valuable suggestions and feedback on these JWK features is great! |
This PR Draft addresses #518
It adds a new member
common_parameters
to JWKs, representing values in the IANA JSON Web Key Parameters Registry which are not specific to any particular value ofkty
, as well as any custom values to be associated with a JWK.There is currently no validation according to the semantics of any of these parameters.
Common Parameters (as they were called in RFC 7517) are automatically imported and exported, and can be explicitly specified for
initialize
using thecommon_parameters
option.During import, specified common parameter keys are converted to symbols.
This PR is mostly API compatible to
main
, with one exception:When trying to import a JWK using the wrong class (as indicated by the
kty
value), the lib now raises aJWT::JWKError
before passing the invalid key to OpenSSL and having an error thrown there.The same happens for unspecified
kty
, which actually makes the import candidate a non-JWK according to RFC 7517:Never ending list of things to do:
kty
specific parameters in thecommon_parameters
memberuse
would be a good candidate to enforce for thekey_finder
)