Closed Keats closed 4 years ago
I only became aware of this lib yesterday because of the bug I was tracking down, and while #74 works, it's not what I would call clean.
So my one thought looking at this code only briefly was that it might be nice to be able to expose some helpers for deserializing the RSA key based on the user knowledge and passing that key down to the API rather than the current method of just trying both. The reason I say helpers would be nice instead of just passing the key directly is that would require the user adding 2 new dependencies, ring
and untrusted
, though another option would of course to be to expose the types and functions needed from those crates as part of the public API of this lib.
In my future plans for ring, I expect the user will be able to create keys in ways other than reading them from byte arrays (files). For example, some users may want to generate a private key in memory and never serialize it. Or, we may support importing keys from the operating system where we never have the raw bytes of the key. And, I think once we have that functionality, people will want to use it with a library like this. So IMO it would be better to delegate all the key object creation to ring other than PEM parsing (since ring doesn't do PEM).
In other words, rather than having a PKCS#8 parsing API in jsonwebtoken, and a "raw DER" parsing API here, i recommend instead just have the user use ring's parsing API to construct a key and pass it into jsonwebtoken.
i recommend instead just have the user use ring's parsing API to construct a key and pass it into jsonwebtoken.
That would require users having to add ring
and untrusted
to their list of direct dependencies, which isn't great in terms of UX.
Also if we somehow decide to have an openssl backend in addition of ring it would make things complicated
That would require users having to add
ring
anduntrusted
to their list of direct dependencies, which isn't great in terms of UX.
In ring, we're gradually phasing out the use of untrusted
in the API. Maybe that will be done in ring 0.15. I don't think it's problematic for people who want to use ring to use use ring's API to construct the key used. That seems much better to me than having this crate (and every crate that uses ring) duplicate ring's API to hide the fact that ring is used.
Also if we somehow decide to have an openssl backend in addition of ring it would make things complicated
I personally think that would hurt the value proposition of the crate and would be a lot of work, so I wouldn't do it. But obviously I'm biased.
I don't think it's problematic for people who want to use ring to use use ring's API to construct the key used. That seems much better to me than having this crate (and every crate that uses ring) duplicate ring's API to hide the fact that ring is used.
Right now I need to bump the major version of this crate everytime ring
gets a major version. If the symbols versioning PR is merged, I won't need to bump it all the time. However if ring
is exposed, I would have to bump on every breaking change even after that.
In other words, rather than having a PKCS#8 parsing API in jsonwebtoken, and a "raw DER" parsing API here, i recommend instead just have the user use ring's parsing API to construct a key and pass it into jsonwebtoken.
@briansmith In our case we have web services written in Rust, Erlang, Ruby and Go. They need to use a same key to verify access tokens in incoming requests. If I generate keys using Ring, I'll get a keypair in pkcs8 DER format instead of just a private key that is, for instance, is used by Erlang crypto library. I will need to parse the keypair in the applications and that seems to me as not a good idea. Sadly there is currently no way to use the same pkcs8 DER key for all the applications, that's why we currently use openssl to generate PEM keys to consume by Erlang apps and pcks8 DER (from the PEM keys) for Rust apps.
Ideally, I would like to have a command line tool (because it just makes things easier for devops engineers) that allow to generate keys in a common format. Maybe at some day such a command line tool will be based on Ring project if we make it possible.
@Keats it seems that it'll take some time to implement all described features for v6
. Can we have an intermediate release with ES256 support before that? Working with the branch creates a bunch of dependencies-related issues.
An intermediate release would have to be a major one sadly. However I can probably merge that PR in the v6 branch and you shouldn't have dependencies issues at that point no?
Merging into master without bumping a new version of crate won't make a difference. Dependencies issues I'm talking about exist because of some other crates are using the current version of jsonwebtoken crate.
An intermediate release would have to be a major one sadly
Maybe, we can have v6 with ES-256 support, and other features in v7? I mean the version is just a number.
Maybe, we can have v6 with ES-256 support, and other features in v7? I mean the version is just a number.Maybe, we can have v6 with ES-256 support, and other features in v7? I mean the version is just a number.
We could but it is annoying for end users to have frequent breaking changes :/
We could but it is annoying for end users to have frequent breaking changes
It always better to have releases available as soon as possible in my opinion. You always can stay on a previous major release, If you don't care about new features. It also shouldn't cause any problem if you're using simversion properly.
I don't have the time to implement that right now so let's get all the PRs in v6. That is going to be messy but at least not block people
The next version is at https://github.com/Keats/jsonwebtoken/pull/75 if people want to try it, I'm trying to get the other outstanding PRs to be merged in it.
The work on next version has started in https://github.com/Keats/jsonwebtoken/pull/91 thanks to @Jake-Shadle
The plan is to add #69 and #87 to it (so 2 more key types: Modulo and Pem) and figure out why some decoding does not work (#90, #77) by adding more tests.
@Jake-Shadle @Keats making this work with PEM would be really useful.. I've thus far failed to use openssl::Rsa pem-to-der helper functions to convert a public key PEM to DER and then make it work correctly with jsonwebtoken's decode
(nube question) how do I reference v7 in a consuming app's cargo.toml?
See https://stackoverflow.com/questions/54196846/how-to-specify-a-certain-commit-in-dependencies-in-cargo-toml for that, just point to the latest commit in the v7 branch and you should be good to go.
Agreed. It would be even nicer if it could load a JWK directly. I can't figure out how to supply the modulus and exponents from the json form.. base64 decoding those strings fails for me
v7 can load a RSA key from a modulus/exponent pair: https://github.com/Keats/jsonwebtoken/blob/next/tests/rsa.rs#L67-L100
I know but how to I easily convert from text format from a jwk:
I'm trying to convert n and e from their encoded form for use in jsonwebtoken
const jwk = { "alg": "RS256", "kty": "RSA", "use": "sig", "x5c": [ "MIIDAzCCAeugAwIBAgIJQjv/H0ysfmAsMA0GCSqGSIb3DQEBCwUAMB8xHTAbBgNVBAMTFGNsYXJrZXpvbmUuYXV0aDAuY29tMB4XDTE3MDgyNjIzNDUwOVoXDTMxMDUwNTIzNDUwOVowHzEdMBsGA1UEAxMUY2xhcmtlem9uZS5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDY/4U3OFFS3+QaST6/XLtIvEQx5ic+APbpaOm1g7H0ow5otrntXsRb1IFNJxBhLG7oWuwTsU+/ZwaM6R4aDCSJRLvgNXCUEEmPNAEZzQx5UiYCU7uqTlCsLIjqaKf9cWAA9KDcUipukNBYbyGOjLxIQU1pkf+HMLcQpDYTq1K4MmOBe45xz1i8I+u+R1tu56dq821kKSazIncCYjP2NsuCq3TOywAhmlOk8t5p0ESfQ1GgjS0EnbhXHD+lgfCWoRJTMWtmreA6Qv+eceAtMGeD0zykxajL/MxYya5P5ad6OGe5Acv90hr27XVAskgUMZFt6WiOOw2/OndeOb2d7m11AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKIJHJKhcYoY5unvKZtzhvN4v4EZMA4GA1UdDwEB/wQEAwIChDANBgkqhkiG9w0BAQsFAAOCAQEAYN/CFEeAKB8CuV8JRlO17bmCspjoDfSj5Q+iAHiC3MSOo2pJEZCADPJ18UAKfXvA8qjpiLyhnAOb/KsFqas0Qo3v0ZHR3M+dKZZzBA9ThKif4S2N4eNdg/Kpcd6xT9nph+K78L91B18G4LJawRuzPt2If3O/vELAY7pWSNpof6Tj171HPEak/39tdiUyXs9k4qRiH4t0DZGgWIIP1e5ZsZ67leBD/+tsdqARHBSX1G7oTmU08JgUVzrFfHunEgwYo+OQa5g87TRi170gCigu8q3OAV4uHrKGp8XdCPVCyE/ZGZCVIefd22nU+cd28o0WKvkFmieBKFLwV0VTItgitg==" ], "n": "2P-FNzhRUt_kGkk-v1y7SLxEMeYnPgD26WjptYOx9KMOaLa57V7EW9SBTScQYSxu6FrsE7FPv2cGjOkeGgwkiUS74DVwlBBJjzQBGc0MeVImAlO7qk5QrCyI6min_XFgAPSg3FIqbpDQWG8hjoy8SEFNaZH_hzC3EKQ2E6tSuDJjgXuOcc9YvCPrvkdbbuenavNtZCkmsyJ3AmIz9jbLgqt0zssAIZpTpPLeadBEn0NRoI0tBJ24Vxw_pYHwlqESUzFrZq3gOkL_nnHgLTBng9M8pMWoy_zMWMmuT-WnejhnuQHL_dIa9u11QLJIFDGRbelojjsNvzp3Xjm9ne5tdQ", "e": "AQAB", "kid": "N0M5NDA5RkI4NjY1QUVERTlDMzE4MkEyRjA4QThCOTI2NTQzNzhFNw", "x5t": "N0M5NDA5RkI4NjY1QUVERTlDMzE4MkEyRjA4QThCOTI2NTQzNzhFNw" }
v7 can load a RSA key from a modulus/exponent pair: https://github.com/Keats/jsonwebtoken/blob/next/tests/rsa.rs#L67-L100
@Keats any interest in also supporting PEM files?
Yes that's the main blocker for the v7 release: https://github.com/Keats/jsonwebtoken/issues/77#issuecomment-520248623 (details from that comment and below).
An alpha version has been released: https://docs.rs/jsonwebtoken/7.0.0-alpha.1/jsonwebtoken/index.html
If anyone has some time to try it and give feedback it would be great. The main change is that the encode/decode functions now take the .pem instead of the der format, it can decode using RSA pub key components and adds RSA PSS.
cc @Jake-Shadle
It's not using the Key
enum anymore but it should be working well for modulus/exponent. The only catch is that right now it takes &str
for them since they are usually b64 encoded and coming from some JSON data.
Hi @Keats - thanks for the version 7 update! I've been look at using this for verifying access and id tokens from Amazon Cognito and in particular the fact that it's now possible to directly pass the RSA exponent and modulus values for the key has been really helpfull.
One thing I have got stuck with though is being able to efficiently handle additional validation of the claims beyond what's handled by Validation
.
I'm making a minimal crate that handles fetching keys from https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
and checks claims like iss
and aud
are set as appropriate for Cognito tokens.
I currently have a KeySet::decode<T>(self, token, validator) -> T
api similar to jsonwebtoken's decode api whereby someone else is responsible for defining their own Claim type and I have helpers to set up a Validation struct depending on whether you're validating a Cognito Id token or access token.
In this case there are some non-standard "client_id"
and "token_use"
claims I want to validate, but because I'm acting as an intermediary that's not responsible for the final claims struct/type that's used I don't have an efficient way to do additional validation after jsonwebtoken does its validation.
Since it's possible for administrators of an AWS Cognito user pool to extend the claims I'm hoping to keep it generic.
It could be good if the claims: Map<String, Value>
that's created as part of validation weren't discarded so that further validation of claims would be straightforward without needing to repeat the base64 decode -> deserialize multiple times. At least in my situation I think it would be good if this map could be added to the returned TokenData and wonder if you'd consider a change like that?
Sorry if that's a bit too off topic for here; I can open another issue if it makes sense.
Thanks again!
@rib @Keats It would be nice to turn validation into a behavior exposed as a trait, such as trait Validator<C>
and allow for anyone to write a custom type that impl's a trait Validator<C>
where C is the custom claim type (or something along these lines?). This ought to facilitate what @rib and others will try to accomplish.
@rib note that @Keats is maintaining this library as a courtesy but isn't currently using it in his own work so needs contributors for heavy lifting such as this. I don't have a pressing need for custom validation (yet) so won't be contributing these changes. Also, a v7 release is imminent. Any related work would contribute to a future release.
I'm not sure I want to make a trait based validation since for 99% of the users, the current approach will work. Adding the encoded claims could be useful but it would expose some serde_json internals (the Map) from the crate.
You can easily add a to_value(&claims).unwrap().as_object().unwrap()
to get the Map back. A bit wasteful since you re-serialize but claims in general should be small enough that it's not a bottleneck.
I'm thinking on whether to change modules/exponent to &[u8] from &str to allow more input types but I don't think I've seen JWK not in JSON format so I don't know whether it's worth changing it.
It doesn't seem ideal that serializing the claims type requires that it has fields for everything you want to validate while the map has everythig contained in the JWT. To be able to get to all the original claims it really doesn't feel ideal to have to separately decode and parse the token again after it's been validated. In total this results in 2x decode and 3x deserialize - and although they are pretty tiny it still doesn't seem good.
At the moment I'm experimenting with a slightly different approach to all of this with a few different ideas:
For the modulus and exponent I was taking those from a jwk so a base64 string was perfect, but yeah maybe there are other use cases where that's not convenient.
Hey everyone! I'm writing a generic JWK crate (like @rib, with the primary motivation of interacting with AWS cognito). I've been playing round with a couple of the most recent commits on this branch, so I thought I'd chime in with my 2c.
I had a few questions and ideas:
I think a decode_raw could be added if you want the Map but the decode by default should still deserialize into a struct by default where you can build additional validation on top of it if needed. Would it already work if you put a Map as the generic type? The default basic JWT should be as easy as possible.
Would it be possible to expose one decode function that takes a key enum?
That was the case in the next branch a while ago but wasn't really great from a user perspective.
Specifying the key components as base64 is convenient, but it does seem slightly better to pass them as a &[u8] from a separation of concerns point of view.
This is likely to happen.
Is there any appetite for also being able to pass elliptic curve key components to the library?
Yes, there were some work on it in a branch before realising it wasn't supported by ring so it was dropped.
I think the thing I'm finding awkward with the deserializing into a struct design (and maybe similar for @JTKBowers if he's also making Cognito middlware) is that there may be multiple consumers of a deserialized token. If jsonwebtoken is considered to be a low level library for dealing with tokens (at least that's how I've been looking to use it) then there will be others that want to build middleware that specifically deals with Cognito or Azure details etc and then there will be a final user and they are the ones that will determine the concrete type which means from this pov (of wanting to incrementally add Cognito specific validaiton) we don't really get to choose to deserialize into a Map.
..hmm, that's not quite true, with your suggestion a middleware can actually get all the info it needs by passing a Map and then it can also offer the user a generic claims struct based api if it then uses ::from_value()
to convert that map to the users struct. The only issue there is that in this case jsonwebtoken is going to basically deserialize from json text into two separate Maps which is completely redundant work that seems like it should be relatively easy to avoid.
I think maybe deserializing into a struct type could be handled closer to the surface of the API as an optional convenience api (maybe even the default api that documentation steers you toward) so internally it would only create the Map needed to validate all the claims. I think then it would be quite easy to expose a decode_raw
api as suggested.
Atm I've gone down a bit of a rabbit hole creating an alternative api more-or-less from scratch, but since I then borrowed heavily from jsonwebtoken it's still not really a million miles away. Maybe if I get a bit further along today I'll just push what I have to a github repo and would be intersted to hear if there are any ideas that could instead make sense to bring back into jsonwebtoken.
If jsonwebtoken is considered to be a low level library for dealing with tokens (at least that's how I've been looking to use it)
That's not really the goal. The goal was to have https://pyjwt.readthedocs.io/en/latest/ in Rust where the decoded claims are in a struct instead of a hashmap. Some parts of the inner API are public (https://docs.rs/jsonwebtoken/7.0.0-alpha.1/jsonwebtoken/crypto/index.html) to ensure people can build other abstractions on it. At the same time I don't really want to make everything public otherwise I can never change anything in the library without a major version.
The main issue with a decode_raw
is that it needs to be multiplied by the number of decode fns which is far from ideal. Adding back a Key
enum could solve that at the cost of UX (and internally it does have an enum like that), which isn't great either.
@JTKBowers would you have the time to try a Key approach again for decoding only? There is already an internal one so it shouldn't be too hard.
As for n/e type, I think <T: ?Sized + AsRef<[u8]>
could work well so people can use whatever.
I mentioned above I was experimenting with an alternative API, so in case it might be of interest here, I ended up making some good progress and having an initial working implementation here:
https://github.com/rib/jwt-rust/blob/master/src/lib.rs
At least initially it was heavily based on jsonwebtoken code. I ported most of jsonwebtoken's unit tests across to this API too, but haven't ported the ecdsa tests yet.
I haven't documented the api yet but an encode->validate round trip currently looks like this:
let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
let header = json!({ "alg": "HS256" });
let claims = json!({
"aud": "test",
"exp": get_time() + 10000,
"my_claim": "foo"
});
let token_str = encode(None, &header, &claims, &alg).await.unwrap();
let verifier = Verifier::create()
.with_audience("test")
.claim_equals("my_claim", "foo")
.build().unwrap();
let claims: Value = verifier.verify(&token_str, &alg).await.unwrap();
Some of the things I think are notable about this API:
The crypo state is contained in an Algorithm
struct (which was a design idea borrowed from java-jwt). This way any associated base64 decoding + pem parsing can be done once up-front. Instead of having a very generic key: &[u8]
it has separate constructors for different algorithms like ::new_hmac
, ::new_rsa_pem_signer
, ::new_rsa_pem_verifier
The Algorithm handles the lower level API for signing and verifying signatures but doesn't care about the structure of the messages themselves.
The Algorithm sign
and verify
apis are async and the idea is that they can abstract a key set in the future which might involve network IO, e.g. to fetch a .jwks
url. (to be handled in a separate project)
The verification gains a lot of flexibility by using a builder pattern for construction, which can hopefully avoid an explosion of top-level verify apis to handle different cases.
The claim verification generalises for custom claims: .claim_equals()
can match values against a constant, .claim_matches()
can match against a regex while .claim_equals_one_of()
and .claim_matches_one_of()
let you match against a set of values or regex patterns. I think it would potentially it would be straight-forward to accept a closure too for any other quirky cases.
The simple verifier.verify() only returns the claims deserialized into whatever type you like (above it's deserialing into a serde_json Value but that could be a custom claims struct. As with jsonwebtoken that implies deserializing at least twice so there is a lower level api verify_for_time()
that returns the claims Map<String,Value>
that must necessarily be deserialized internally and also lets you specify the 'now' timestamp.
I'd be very interested to hear any thoughts / feedback about this design, and would be happy to see any of it be folded into jsonwebtoken if it makes sense.
Hmm this is definitely too different from the current goal. I think we can lift some ideas from it though!
PemEncodedKey
but not exposing the struct to keep that internal).EncodingKey
(secret, pem, der) and DecodingKey
(secret, pem, der, n/e, ecdsa component once ring supports it) enums to encode/decodeResult<()>
I don't want this crate to do any fetching even in the future so no async in there, too many potential things people might want to control there (eg caching) to be inside a library.
Overall the current API would only change for the EncodingKey/DecodingKey but it would stay the same way otherwise.
I definitely won't have the time to work in the near future on that so it would have to come as a PR.
I don't want this crate to do any fetching even in the future so no async in there, too many potential things people might want to control there (eg caching) to be inside a library.
yeah, I also wasn't ever anticipating that this implementation would ever handle fetching jwks key sets itself, but was just keeping the possibility that it would be extensible (i.e. another middleware could essentially provide it's own implementation of some Algorithm
trait which could potentially wrap a key set such as a remote jwks set.
Actually I'm having second thoughts about this aspect because in practice I actually already have a separate project where I'm handling jwks fetching and it seems pretty much fine to do on top of this instead - and it's not obvious that it would be any better if it was abstracting over an Algorithm instead.
It also means I could drop the optional kid
argument for the encode
which is only there to possibly allow this key set abstraction.
@Keats I started to experiment with item 3 (validator dependency injection). The boolean option fields in the Validation type are only applicable to the default validation logic presented in the validate
fn. Injecting custom validation logic changes the need for have such flags. If I'm injecting my own validation closure, I control the logic rather than rely on checking flag fields. Maybe, rather than replace the entire validation logic, use a closure to augment it. fn validate
can act as a core validator and a closure may be called additionally, if one is defined.
Btw, for reference, since I also had doubts about it in the end; I updated https://github.com/rib/jwt-rust/ to only have a synchronous API abandoning the idea that an Algorithm could abstract a key set in the future.
The custom validation fn would only be there to enhance the existing Validation, eg it would be called after all the other validation if it is present. We probably need to add an error type like CustomValidation and an easy way to create a jsonwebtoken error from that fn.
On Sat, 30 Nov 2019, 16:45 Darin, notifications@github.com wrote:
@Keats https://github.com/Keats I started to experiment with item #3 https://github.com/Keats/jsonwebtoken/pull/3 (validator dependency injection). The boolean option fields in the Validation type are only applicable to the default validation logic presented in the validate fn. Injecting custom validation logic changes the need for have such flags. If I'm injecting my own validation closure, I control the logic rather than rely on checking flag fields. Maybe, rather than replace the entire validation logic, use a closure to augment it. fn validate can act as a core validator and a closure may be called additionally, if one is defined.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Keats/jsonwebtoken/issues/76?email_source=notifications&email_token=AAFGDI5GIKBNGBSCB4OMGNDQWKDAJA5CNFSM4GUG7IB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFQLGNA#issuecomment-559985460, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFGDI2TXSXFABDXOJLMV6TQWKDAJANCNFSM4GUG7IBQ .
@JTKBowers would you have the time to try a Key approach again for decoding only? There is already an internal one so it shouldn't be too hard.
I'd be happy to! Let me know what I can do.
I'm thinking point 1 and 2 of https://github.com/Keats/jsonwebtoken/issues/76#issuecomment-559959232 Point 1 could be done transparently with an EncodingKey enum so users can just save that struct in lazy_static or whatever and only decode it once.
@Keats why not target a cutoff date for any additional enhancements so that v7 can be released this year? I think I can make time to finish work on an extend_validation
api in the near future, but even this functionality is a scope creep.
The extend_validation can be added in a non-breaking way later on. The Encoding/Decoding key cannot and this is already v7, I want the API to stabilise
@Keats in other words, you're saying that the final blocking dependency on a v7 release is the work related to Encoding and Decoding Key? @JTKBowers
That sounds like putting a lot of pressure on @JTKBowers but essentially I want to make sure jsonwebtoken v7 is stable for at least a year in terms of API.
Encoding/Decoding keys should be pretty easy to implement but would allow the API to be stable and performant.
@Keats If I understand correctly, you want to capture as many of the valuable ideas now for v7 as you can because you want v7 crate to be the standard for year that follows its release. Sounds fair, but you will have to determine what is good enough to ship rather than wait indefinitely for more good ideas, right? The goal post was moved not too long ago.
Regarding extend_validation, I've been considering tradeoffs related to how to inject a Validation type with a closure. "Boxed trait object" is less visible and does not change the type signature, but not as performant as "unboxed closure". jsonwebtoken is performance-sensitive, so I prefer whichever approach is fastest (even at the cost of changing the type signature to Validation<V> where V: ExtendValidation
, or something similar)
https://stackoverflow.com/questions/27831944/how-do-i-store-a-closure-in-a-struct-in-rust
thoughts?
I would guess that any performance concern from closure differences should be a drop in the ocean for validating a few token clams, so maybe that shouldn't be a concern? base64 decode + e.g. rsa signature validation is surely going to be much much more costly that an extra pointer dereference?
For now I think jsonwebtoken has some other lower-hanging ways to opimize it before this is really a performance trade off - I guess ergonomics should be a bigger concern for supporting a closure for validation.
I found that an extended_validation: Option<Box<dyn Fn(...) -> Result<()>>>
field can exist within the Validation type only if ALL of the derived proc macros are removed (Debug, PartialCmp, Clone). Removing them does not seem to interfere with the library nor tests. Keeping these proc macros seems to push a solution towards the initial one I proposed, using a generic and trait Validate. If anyone can think of an alternative, please by all means share your idea.
Assuming we go with the trait object for extended_validation, I'm not really sure as to what the function signature should be for the extended_validation closure. The Claims HashMap param, undoubtedly, will be the first param, but as for a second param, my best guess is a serde::Value. This seems like the most flexible.
Thoughts?
@Dowwie I'd be curious to know what you think of the validation solution I came up with in jwt-rust. It didn't expose a closure so far but it is generalised to support custom claims. The most common claims are particularly simple to check with something like:
let verifier = Verifier::create()
.issuer("http://some-auth-service.com")
.audience("application_id")
.subject("subject")
.build();
and custom claims can be handled in a number of ways like:
let verifier = Verifier::create()
.claim_equals("my_claim0", "value") // exact match
.claim_matches("my_claim1", "value[0-9]") // regex
.claim_equals_one_of("my_claim2", &["value0", "value1"]) // match against a set of value
.claim_matches_one_of("my_claim3", &[regex0, regex1]) // a set of regex matches
.build();
Out of curiousity do you have a use case that couldn't be handled with this amount of generality?
There are quite a few changes happening in the PRs: more input format for RSA (#69, #74), ECDSA signing & verification (#73) as well as some Validation changes.
I have already removed the
iat
check in thenext
branch since it isn't something that should be checked.Right now,
Validation::algorithms
is avec
. I don't remember why but it shouldn't be the case, it should be analgorithm: Algorithm
instead, I will accept a PR for that or do it myself later.69 also adds a standalone
verify_rsa
fn, which I'm wondering if we can somehow streamline it with the rest of the crate.Since Rust doesn't have default parameters, we always have to pass a
Validation
struct currently. Maybe we can put the decoding onto this struct instead so you get something like:This way we don't have a single function where we are trying to fit all arguments inside and the user has to select explicitely which decode fn to use. This solves the
vec
of algorithms at the same time and allows having better documentation for each. The downside is duplication of those functions/docs for the various digest values (decode_hs256
,decode_hs384
,decode_hs512
for each algo).Any other ideas/criticisms/things missing?
ccing the people involved in various issues/PRs recently @AaronFriel @jbg @Jake-Shadle @matthew-nichols-westtel @greglearns