jwt-cli
jwt-cli copied to clipboard
Support encoding JWT using JWKS string
Summary
This is related to use cases described in both #119 and #128.
I'd like to run jwt encode by providing my own JWKS instead of a plaintext --secret value. For example:
# jwt encode ... [--secret|--jwks]
$ MY_JWKS='{"keys":[{"alg":"HS256","k":"hS1H1jxz1fgBlXZGvuPxJHOnZxKsoAlvTncmFD-qEkc","key_ops":["sign","verify"],"kid":"MY_KEY_ID","kty":"oct"}]}'
$ jwt encode --kid MY_KEY_ID ... --jwks "$MY_JWKS"
where MY_JWKS can be retrieved from some HTTPS endpoint or generated locally using the jose CLI:
# https://github.com/latchset/jose
$ jose jwk gen -s -i '{"alg":"HS256","kid":"MY_KEY_ID"}'
{"keys":[{"alg":"HS256","k":"hS1H1jxz1fgBlXZGvuPxJHOnZxKsoAlvTncmFD-qEkc","key_ops":["sign","verify"],"kid":"MY_KEY_ID","kty":"oct"}]}
and jwt-cli would use the JWK in the provided keyset by matching the mandatory --kid value.
Besides just adding support for the JWKS standard, it allows using 256-bit (or whatever size) base64-encoded secrets that is in the JWKS k value. The --secret parameter is currently unable to use a non-Unicode string value, throwing the following error if given a binary string:
$ jwt encode --kid MY_KEY_ID ... --secret "$(base64 -d <<< "hS1H1jxz1fgBlXZGvuPxJHOnZxKsoAlvTncmFD-qEkc")"
thread 'main' panicked at 'unexpected invalid UTF-8 code point', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.33.3/src/args/arg_matches.rs:118:40
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Thanks for writing this up @erhhung! I'm not familiar with JWK/JWKS, so this is a bit new for me.
Taking an initial look, however, I don't think jwt-cli would be able to fully implement the standard. The underlying libray this project uses, keats/jsonwebtoken would allow us to support HMAC and RSA keys, since it provides a method to decode with ECDSA components, but not RSA components. Encoding is another matter, as this project would need to create the keys first, and it doesn't look like ring supports that.
What are your thoughts?
I would love to see this feature too.
You don't need to generate keys before encoding first. You just need to require a JKW set that also contains the private key information. You can play with different JWK sets here https://mkjwk.org/ to get a better understanding of what that entails.
As far as I can tell keats/jsonwebtoken has support for at least ES256 an ES384 these days. It might not be everything but some support is much better than no support.
Unfortunately I don't have a lot of time to work on this at the moment (hence the delay here!) so if anyone would like to open a PR for this, I'd be happy to review!