Comments (19)
The (OpenBanking) spec explicitly says clients are allowed to set
cty
.
FWIW, I contacted the secretary of the OpenBanking Working Group to indicate there is a conflict between the two specifications. We'll see if/how there might be a process to modify their specification to be congruent.
from jjwt.
I should clarify that the open banking DCR spec does not reference cty
at all, which I think is what you'd expect. It's the Confirmation of Payee (CoP) DCR spec that I shared above which references cty. CoP is a different service to open banking but they currently share the same ecosystem for onboarding. I don't think OBIE are responsible for the CoP specs though.
from jjwt.
As an aside, I've just found this in the spec we're using for one of the services. The spec explicitly says clients are allowed to set
cty
.
I'm assuming you're referring to the OpenBanking spec?
If so, that spec directly conflicts with the recommendations in JWT RFC 7519 (Section 5.2) that the cty
header is only intended to be used to support nested JWTs:
In the normal case in which nested signing or encryption operations
are not employed, the use of this Header Parameter is NOT
RECOMMENDED. In the case that nested signing or encryption is
employed, this Header Parameter MUST be present; in this case, the
value MUST be "JWT", to indicate that a Nested JWT is carried in this
JWT.
In fact, it is the very absence of a cty
header that indicates to JWT libraries per RFC 7519 that the payload is expected to be Claims JSON.
Otherwise, the cty
header must be handled/processed by the application (not the JWT library). Per JWS RFC 7515, Section 4.1.10:
This parameter is ignored by JWS implementations; any processing of this
parameter is performed by the JWS application.
The reason for this is that there is no media type for Claims JSON (e.g. application/jose.claims+json
or similar); it is impossible for a JWT library to see a media type of json
or application/json
and 'know' that it should be parsed not only as JSON, but also interpret/validate that JSON as Claims name/value pairs per the JWT RFCs.
In other words, if a JWT payload was application/json
and that JSON represented an application data model (e.g. a JSON document that represented an invoice, purchase order, etc), a JWT library can't (and shouldn't) process that as Claims JSON.
So how does a JWT library then 'know' when to treat the payload as Claims vs any other JSON data structure? The only mechanism identified in the JWT RFC 7519 is the absence of the cty
header when the payload is not Claims or a Nested JWT.
Someone should definitely bring this up to the OpenBanking spec committee because the very presence of their cty
recommendation contradicts RFC 7519.
JJWT's primary responsibility is to implement the RFC behavior specified by the various specifications managed by the JOSE Working Group. Additional specifications beyond that (e.g. OpenID Connect, OpenBanking, etc) is not currently a design goal (but could be in the future), as anything built on top of JOSE RFCs are expected to be symbiotic, not conflict with them.
BUT! That doesn't mean we can't/won't implement enhancements that can allow this additional behavior, or try to help to find workarounds, etc. We'll do our best, I'm just stating that the JOSE WG RFCs are the primary goal and anything in conflict or contradictory to them are secondary goals.
from jjwt.
- I think we lose the
Jws
object? i.e.Jws<byte[]>
is passed into the visitor andClaims
are returned. There's no way for us to end up withJws<Claims>
because we don't have an easy way to reconstruct theJws
.
That's true at the moment, but it's a trivial exercise to implement the Jws<Claims>
interface directly in your project and return that from a utility method so the rest of your application code doesn't need to know about these underlying details. For example:
...
Jwt<?, ?> jwt = Jwts.parser().build()/*... */.parse(jws);
Claims claims = jwt.accept(visitor);
Jws<?> jws = (Jws<?>)jwt;
// ClaimsJws in your project implements Jws<Claims>
return new ClaimsJws(jws.header(), claims, jws.getSignature(), jws.getDigest());
I think that's a reasonable (albeit not ideal) workaround until we can finalize a ContentTypeHandler
concept. I hope that helps!
from jjwt.
Hi @icecreamhead!
Thank you for reaching out! Let me explain what's happening, and see if we can find a workaround for you.
As you noted, this change is purely driven by the RFC, and the RFC is quite clear that libraries (e.g. JJWT) are not to interpret payloads that have an assigned content type, and it must be the application (i.e. your code). Per RFC 7515, Section 4.1.10, "cty" (Content Type) Header Parameter:
This is intended for use by the application when more than one kind of object could be present in the JWS Payload; the application can use this value to disambiguate among the different kinds of objects that might be present.
and, most important for JJWT:
This parameter is ignored by JWS implementations; any processing of this parameter is performed by the JWS application.
So the spec is implicitly saying:
"If the cty
header is set, the payload can be literally anything, and it's not reasonable for a library to know how to process the payload because it's application-specific. Because of this, the application is responsible for handling payload themselves".
Consequently, if JJWT >= 0.12.0
sees that the cty
header has a non-empty value, it won't parse the payload at all (completely skips that), because JJWT has no way (currently) to figure out how to handle the payload.
BUT! It doesn't mean that JJWT ignores security. If found to be a JWS, JJWT does indeed perform signature verification, and if successful, constructs a Jws
object, but the payload returned in that Jws
instance will be a byte[]
because JJWT can't parse it as JSON; it instead 'passes it along' to your application code.
Consequently, the reason you're seeing that exception is that because, per the parseSignedClaims
JavaDoc, that method is a convenience that simply delegates to:
-
parse(compact)
which returns aJwt<?,?>
instance, and then -
immediately calls the type-asserting
Jws.CLAIMS
Visitor to ensure the parsedJwt
is what you expect it to be.Jws.CLAIMS
is a simple visitor that merely asserts that what was parsed was- a
Jws
instance (not just aJwt
orJwe
), and - that the payload is a
Claims
instance (and not any random payload).
and if not, throws the exception you see.
- a
So, in JJWT's current form, you have two choices:
-
Don't call
parseSignedClaims
because of the type validation in step 2 above. You can call justparse
, get back aJwt<?, ?>
yourself. If the instance is aJws
and the payload is aClaims
, then nocty
header was set. If the instance is aJws
and the payload is abyte[]
, then thecty
header was set, and you'll need to parse it yourself based on thecty
value. You could theoretically then parse it via a JSON parser, and pass the resultingMap<String,?>
to aJwts.claims()
builder if desired to get a finalClaims
instance. -
Communicate with your upstream jwt token issuer that what they're doing is causing problems because of the RFC. Just because you don't control how they issue the token doesn't mean they won't listen to a bug report you file, especially when they hear that they're violating the spec. Resolving RFC non-compliance is usually a much bigger driving force for prioritization than a customer/client/recipient just saying "can you please change how this works".
from jjwt.
@icecreamhead my immediately preceding comment was to explain why things are the way they are, and how to potentially address your needs today, without JJWT code changes. This comment addresses a discussion of how we might support cty
behavior in the future.
When working towards the 0.12.0 release, and its associated cty
logic per the RFC, I did actually envision enabling a custom ContentTypeHandler
(or similar) concept where, if a cty
header was encountered, the header and payload byte[]
would be delegated to the handler for conversion. The handler would return an Object
of whatever the byte[]
became, and that would be set as the Jws
payload instance, e.g. new DefaultJws(JwsHeader, whateverTheHandlerReturned);
And the application could register various type handlers with the JwtParserBuilder
to perform this logic automatically during parsing before a complete Jwt
instance was returned.
The reason this wasn't done for 0.12.0 was due to time constraints and complexity. The JWE and JWK stuff was so large and comprehensive, and delayed for quite a while, we just had to get it out. And considering that JJWT is spec-compliant with regard to the RFC, it made sense.
The other reason was content-type/media-type identifier parsing, and registration of various handler types. If you've ever seen the Spring Framework's (very thorough and robust) MimeType
and MediaType
pluggable support, you know how complex this could end up being, and it didn't make sense replicating a similar framework for JJWT, especially when the JWT RFC is clear that the application should be handling this stuff to begin with.
Perhaps a middle ground could be made, at least initially, where JJWT has such a cty
handler concept as a single simple interface, and, the application is free to plug in its own implementation to do whatever it wants. Over time this could be made more robust by providing out-of-the-box MediaType
converters (a la Spring), but I'm not sure that'd be necessary, nor would I be sure that we'd even want JJWT to be in that business of maintaining such a thing when it's an application-specific concern to begin with.
Anyway, I hope these comments have been helpful in understanding why we made those various decisions.
from jjwt.
but if they specify json, then I think we should continue to parse the claims as if the field weren't specified at all.
Just noting in the general case, this doesn't appear to be a viable solution: If the cty
indicates JSON, JSON can be any structure, even non-Object structures (string or number literals, arrays, etc). Claims are not only JSON, but they are JSON with an additional set of parsing/parameter constraints.
In other words, a payload can definitely be JSON, and any kind of JSON at all. Claims are a further restriction on JSON structure/parameters, so there needs to be additional information in a media type identifier to indicate "not only is this JSON, but it is JWT Claims JSON" in order to (correctly) parse it into Claims.
There is no IANA-registered media type for Claims JSON. If there was it'd be something like application/joseclaims+json
(or similar). This is why if the payload is Claims JSON, the cty
header should be omitted entirely, because there's no standard media type to indicate Claims.
from jjwt.
Hi @lhazlewood, thank you for a speedy, comprehensive and well-reasoned response. It's genuinely appreciated!
Unfortunately, asking the upstream token issuers to fix their JWSs is out of the question for us. My use-case is for the UK Open Banking & payee confirmation ecosystem, of which there are hundreds of independent participants. We've observed that the majority actually are setting the cty field on their tokens.
We actually have implemented your first suggestion of capturing the byte[] and parsing the claims ourselves, but this feels like an unnecessary overhead when the library can (and has previously) done the legwork for us.
I think the aspect of the behaviour that doesn't make sense to me is that by invoking parseSignedClaims
, we're signalling to the library that we expect a claims payload to be present, so the fact that the library explicitly doesn't attempt to read the payload when we've indicated what it should be just seems a bit odd.
My request would be to always try to decode the claims when parseSignedClaims
is invoked. If deserialisation fails then it's my problem as an application developer to handle that. Alternatively, a forceParse
option on the parser builder could be added to explicitly indicate that I want to decode the payload, regardless of the content type.
from jjwt.
The other minor smell is that DefaultJws
is in the impl
package which suggests that we shouldn't construct instances of it ourselves. This means to construct an instance of Jws<Claims>
containing our manually-deserialized claims payload, we need to implement our own subclass of the Jws
interface, which is basically a duplicate of DefaultJws
.
from jjwt.
Hi @lhazlewood, thank you for a speedy, comprehensive and well-reasoned response. It's genuinely appreciated!
Happy to help! Let's see if we can keep working on a better solution...
We've observed that the majority actually are setting the
cty
field on their tokens.
That's frustrating to hear that they do that; it is in direct conflict with the RFC. It explicitly says, if the payload is JSON Claims, that cty
is NOT RECOMMENDED (RFC emphasis, not mine). Upstream providers definitely should be told they're causing downstream problems. I know they may not listen to your team, but no one will try to fix it if they're not told 🤷 .
We actually have implemented your first suggestion of capturing the byte[] and parsing the claims ourselves,
Out of curiosity, what is the media type you see being used for most of these? Is it always application/json
(or just shortened json
per RFC shortening syntax recommendations)? Or anything different that those?
but this feels like an unnecessary overhead when the library can (and has previously) done the legwork for us.
Agreed, this is a pain, I'd like to have a more elegant solution now that I understand what you're experiencing.
I think the aspect of the behaviour that doesn't make sense to me is that by invoking
parseSignedClaims
, we're signalling to the library that we expect a claims payload to be present
Ahah, I think we're making progress 😄. Yes, at the moment, those methods are purely conveniences. parseSignedClaims
is just an alias for:
parse(compact).accept(Jws.CLAIMS);
So it is parsed, per normal RFC parsing rules (and cty
rules/expectations), and only then asserted that the resulting Jwt
instance is a Jws
and has a Claims
payload. There are no 'hints' conveyed from parseSignedClaims
to the general-purpose parse(compact)
method call.
Even so, let's assume we did convey such a hint to the parse
implementation.
What if the cty
header is application/octet-stream
(for example)? It is often not safe to blindly parse content as JSON, especially if the header indicates that it contains something else. Substitution attacks have been prevalent in other JWT libraries with naive parsing approaches, so we tend to think really cautiously about these kinds of things.
I suppose at least after verifying the signature, the risks for blind parsing are lessened, but still we have to be really careful about security implications.
Alternatively, a
forceParse
option on the parser builder could be added to explicitly indicate that I want to decode the payload, regardless of the content type.
I'd be hesitant to add that due to the security implications.
But I'm wondering if a simple ContentTypeHandler
concept (or similar) might allow a reasonable solution. For example:
Jwts.parser().cty(handler)...
And the handler would be called when detecting a cty
value. Then the application developer configuring their own handler implementation can do whatever logic they like, from blindly ignoring the value to converting payloads to Claims
or images/documents/etc, or anything in between.
At least that way it would be quite intentional by the app developer, at least assuming they understood the security repercussions of purposefully ignoring any indicated cty
value. Implementing a callback handler like this requires slightly more forethought/insight than a blind 'forceParse' option which could be (very) easily abused and always set to true
when an app dev just wants to 'get on with testing, and come back to this later' (and never actually do it 😉 ).
Anyway, I'm just thinking 'out loud', and still very interested in finding a clean solution that makes things simple for people while still enabling strong security by default.
from jjwt.
Out of curiosity, what is the media type you see being used for most of these? Is it always application/json (or just shortened json per RFC shortening syntax recommendations)? Or anything different that those?
We've observed a mix of json
and application/json
for tokens we've actually investigated, but we don't bother to capture it programmatically so it's possible there have been others.
But I'm wondering if a simple ContentTypeHandler concept (or similar) might allow a reasonable solution.
I think this would be ideal for us. I'd be more than happy to throw a PR together if it helps?
from jjwt.
Out of curiosity, what is the media type you see being used for most of these?
We've observed a mix of
json
andapplication/json
for tokens we've actually investigated, but we don't bother to capture it programmatically so it's possible there have been others.
That's helpful, thanks.
But I'm wondering if a simple ContentTypeHandler concept (or similar) might allow a reasonable solution.
I think this would be ideal for us. I'd be more than happy to throw a PR together if it helps?
That would be appreciated, but as I dug into this potential change more, it's not exactly simple:
- A handler would need things given to it, for example, the
Header
, maybe the configuredDeserializer<Map<String<?>>
and I'm not sure if anything else. - The other thing we might want to work on in the same PR is the parsing 'hint' concept. The parse/visitor thing is fine, but I'm not sure if this can be made better. At the least, perhaps improve the exception messages thrown by the visitors to more clearly indicated what was received vs what was expected.
- The big one: right now, a JJWT payload that is returned to the application is only one of two things: a
Claims
instance (if a compact JWT and acty
header isn't set), or abyte[]
instance if thecty
header is set. If we introduce such a thing as a content type handler, the return type from the various.parse*
methods should reflect the already-converted data type, for example:
Jws<?> parseSignedContent(CharSequence jws);
which is in conflict with the existing (0.12.x
) signature of Jws<byte[]> parseSignedContent(jws);
In other words, a ContentTypeHandler
(or whatever it's called) should perform the type-conversion and there would never be a Jws<byte[]>
method signature on the parser.
I don't know how difficult a change that would/will be, but it's not exactly trivial.
from jjwt.
@icecreamhead in thinking of the Visitor
pattern more, I think that actually can be the 'handler' concept. A Visitor
allows logic, it's just that the default only asserts type expectations. But it can do anything really.
You could just implement the JwtVisitor
interface yourself (or subclass SupportedJwtVisitor
) and do what you want in your visit(jws);
implementation. For example (assuming Jackson):
public class AlwaysClaimsVisitor extends SupportedJwtVisitor<Claims> {
@Override
public Claims onVerifiedContent(Jws<byte[]> jws) {
// if cty header is set, application needs to convert as necessary:
byte[] payload = jws.getPayload();
ObjectMapper objectMapper = new ObjectMapper(); // or get other application singleton
Map<String,?> map = (Map<String,?>)objectMapper.readValue(payload, Map.class);
return Jwts.claims().add(map).build();
}
@Override
public Claims onVerifiedClaims(Jws<Claims> jws) {
return jws.getPayload();
}
}
and then use that visitor:
AlwaysClaimsVisitor visitor = new AlwaysClaimsVisitor();
Jwt<?, ?> jwt = Jwts.parser().build()/*... */.parse(jws);
Claims claims = jwt.accept(visitor);
This seems like a pretty clean workaround, no? The visitor is your 'handler' implementation, and the existing API already supports this use case.
This seems pretty clean, but I could be missing something. Please let me know your thoughts!
from jjwt.
I managed to get the handler pattern working (and correctly inferring the output type) but the code isn't pleasant. I'll stick it on a branch.
I think you're right that the visitor pattern is the right solution (it's what we've switched to right now in lieu of parseSignedClaims()
) but I have two problems with it:
- We have to write extra code to achieve functionality that's already baked into the library.
- I think we lose the
Jws
object? i.e.Jws<byte[]>
is passed into the visitor andClaims
are returned. There's no way for us to end up withJws<Claims>
because we don't have an easy way to reconstruct theJws
.
from jjwt.
As an aside, I've just found this in the spec we're using for one of the services. The spec explicitly says clients are allowed to set cty
.
from jjwt.
@icecreamhead What does a header and payload look like for a openbanking JWS (use fake data)?
From a quick look at the docs, it seems some registered claims from the JWT spec are part of the openbanking JOSE header? e.g.
{
"alg": "RS512",
"kid": "90210ABAD",
"b64": false,
"http://openbanking.org.uk/iat": 1501497671,
"http://openbanking.org.uk/iss": "C=UK, ST=England, L=London, O=Acme Ltd.",
"http://openbanking.org.uk/tan": "openbanking.org.uk",
"crit": [ "b64", "http://openbanking.org.uk/iat", "http://openbanking.org.uk/iss", "http://openbanking.org.uk/tan"]
}
This seems to imply there are other validation steps that should happen:
- The verifier must validate that the
typ
header if specified has the value JOSE. - The verifier must validate that the
cty
header to ensure that the payload is of the expected mime type. - The verifier must ensure that the specified
alg
is one of the algorithms specified by OBIE. - The verifier must ensure that the specified
kid
is valid and a public key with the specified key Id can be retrieved from the Trust Anchor. - The verifier must ensure that the
b64
claim is set to false. - The verifier must ensure that the
http://openbanking.org.uk/iat
claim has a date-time value set in the past. - The verifier must ensure that PSP bound to the
http://openbanking.org.uk/iss
claim matches the expected PSP. - The verifier must ensure that
http://openbanking.org.uk/tan
claim contains the DNS name of a Trust Anchor that it trusts. - The verifier must ensure that the
crit
claim does not contain additional critical elements.
Personally, I'm a fan of this logic being moved into the header vs the payload, but that is a little off spec (per the JWT/JWS rfcs)
We could make sure this functionality is exposed in JJWT though for these types of use cases (as @lhazlewood mentioned above ContentTypeHandler
). 🤔 Potentially creating a module that wraps the open banking jjwt-openbanking
(I know know enough about the openbanking world to know if that would be useful), but either way, we should create a doc with an example. Any chance you can help with an example?
from jjwt.
I think dynamic client registration is the only place we actually receive fully-fledged JWSs.
Here's an example of a registration request:
eyJraWQiOiJlSTFZRF96c2ZURGliSTN5aHdzbGJQNVVHT2MiLCJ0eXAiOiJKV1QiLCJhbGciOiJQUzI1NiJ9.eyJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiLCJhdXRob3JpemF0aW9uX2NvZGUiLCJyZWZyZXNoX3Rva2VuIl0sImFwcGxpY2F0aW9uX3R5cGUiOiJ3ZWIiLCJpc3MiOiJtMUxpUzNxTDVZM0FuTnpxT2pESDd0IiwidGxzX2NsaWVudF9hdXRoX3N1YmplY3RfZG4iOiJDTj0wMDE1ODAwMDAxNmk0NFZBQVEsMi41LjQuOTc9UFNER0ItRkNBLTczMDE2NixPPVN0YXJsaW5nIEJhbmsgTGltaXRlZCxDPUdCIiwicmVkaXJlY3RfdXJpcyI6WyJodHRwczovL3RlYXBvdHByb2R1Y3Rpb25zLnRlc3QvcmVkaXJlY3QxL2Zsb3ciXSwidG9rZW5fZW5kcG9pbnRfYXV0aF9tZXRob2QiOiJ0bHNfY2xpZW50X2F1dGgiLCJhdWQiOiIwMDE1ODAwMDAxNmk0NFZBQVEiLCJzb2Z0d2FyZV9pZCI6Im0xTGlTM3FMNVkzQW5OenFPakRIN3QiLCJzb2Z0d2FyZV9zdGF0ZW1lbnQiOiJleUpoYkdjaU9pSlFVekkxTmlJc0ltdHBaQ0k2SWtWalNFUllhV2xtVFZsWmIwRnpNRUZQWjJsdmJXOTJhMHd3YzBwa2RVRk1lRmx3VTFNM1pUbFBWVms5SWl3aWRIbHdJam9pU2xkVUluMC5leUpwYzNNaU9pSlBjR1Z1UW1GdWEybHVaeUJNZEdRaUxDSnBZWFFpT2pFM01EWXdNamM0TVRJc0ltcDBhU0k2SWpWak9ERTJOemxsWkRBM05UUmlZalVpTENKemIyWjBkMkZ5WlY5bGJuWnBjbTl1YldWdWRDSTZJbk5oYm1SaWIzZ2lMQ0p6YjJaMGQyRnlaVjl0YjJSbElqb2lWR1Z6ZENJc0luTnZablIzWVhKbFgybGtJam9pYlRGTWFWTXpjVXcxV1ROQmJrNTZjVTlxUkVnM2RDSXNJbk52Wm5SM1lYSmxYMk5zYVdWdWRGOXBaQ0k2SW0weFRHbFRNM0ZNTlZrelFXNU9lbkZQYWtSSU4zUWlMQ0p6YjJaMGQyRnlaVjlqYkdsbGJuUmZibUZ0WlNJNklrUmxiVzh2YzJGdVpHSnZlQ0JwYm5SbGNtNWhiQ0IwWlhOMGFXNW5JaXdpYzI5bWRIZGhjbVZmWTJ4cFpXNTBYMlJsYzJOeWFYQjBhVzl1SWpvaVQyNXNlU0IxYzJWa0lHbHVkR1Z5Ym1Gc2JIa3VJaXdpYzI5bWRIZGhjbVZmZG1WeWMybHZiaUk2SWpBdU1TSXNJbk52Wm5SM1lYSmxYMk5zYVdWdWRGOTFjbWtpT2lKb2RIUndjem92TDNOMFlYSnNhVzVuWW1GdWF5NWpiMjBpTENKemIyWjBkMkZ5WlY5eVpXUnBjbVZqZEY5MWNtbHpJanBiSW1oMGRIQnpPaTh2YzNSaGNteHBibWRpWVc1ckxtTnZiU0lzSW1oMGRIQnpPaTh2ZEdWaGNHOTBjSEp2WkhWamRHbHZibk11ZEdWemRDSXNJbWgwZEhCek9pOHZkR1ZoY0c5MGNISnZaSFZqZEdsdmJuTXVkR1Z6ZEM5eVpXUnBjbVZqZERFdlpteHZkeUpkTENKemIyWjBkMkZ5WlY5eWIyeGxjeUk2V3lKUVNWTlFJaXdpUVVsVFVDSmRMQ0p2Y21kaGJtbHpZWFJwYjI1ZlkyOXRjR1YwWlc1MFgyRjFkR2h2Y21sMGVWOWpiR0ZwYlhNaU9uc2lZWFYwYUc5eWFYUjVYMmxrSWpvaVJrTkJSMEpTSWl3aWNtVm5hWE4wY21GMGFXOXVYMmxrSWpvaU56TXdNVFkySWl3aWMzUmhkSFZ6SWpvaVFXTjBhWFpsSWl3aVlYVjBhRzl5YVhOaGRHbHZibk1pT2x0N0ltMWxiV0psY2w5emRHRjBaU0k2SWtkQ0lpd2ljbTlzWlhNaU9sc2lRVWxUVUNJc0lrRlRVRk5RSWl3aVVFbFRVQ0pkZlN4N0ltMWxiV0psY2w5emRHRjBaU0k2SWtsRklpd2ljbTlzWlhNaU9sc2lVRWxUVUNJc0lrRkpVMUFpTENKQlUxQlRVQ0pkZlN4N0ltMWxiV0psY2w5emRHRjBaU0k2SWs1TUlpd2ljbTlzWlhNaU9sc2lRVWxUVUNJc0lsQkpVMUFpTENKQlUxQlRVQ0pkZlYxOUxDSnpiMlowZDJGeVpWOXNiMmR2WDNWeWFTSTZJbWgwZEhCek9pOHZjM1JoY214cGJtZGlZVzVyTG1OdmJTSXNJbTl5WjE5emRHRjBkWE1pT2lKQlkzUnBkbVVpTENKdmNtZGZhV1FpT2lJd01ERTFPREF3TURBeE5tazBORlpCUVZFaUxDSnZjbWRmYm1GdFpTSTZJbE4wWVhKc2FXNW5JRUpoYm1zZ1RHbHRhWFJsWkNJc0ltOXlaMTlqYjI1MFlXTjBjeUk2VzNzaWJtRnRaU0k2SWxSbFkyaHVhV05oYkNJc0ltVnRZV2xzSWpvaVpHVjJaV3h2Y0dWeVFITjBZWEpzYVc1blltRnVheTVqYjIwaUxDSndhRzl1WlNJNklpczBOREl3SURNNE5UY2dOemN4T1NJc0luUjVjR1VpT2lKVVpXTm9ibWxqWVd3aWZTeDdJbTVoYldVaU9pSkNkWE5wYm1WemN5SXNJbVZ0WVdsc0lqb2lhR1ZzY0VCemRHRnliR2x1WjJKaGJtc3VZMjl0SWl3aWNHaHZibVVpT2lJck5EUXlNQ0F6T0RVM0lEYzNNVGtpTENKMGVYQmxJam9pUW5WemFXNWxjM01pZlYwc0ltOXlaMTlxZDJ0elgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OXJaWGx6ZEc5eVpTNXZjR1Z1WW1GdWEybHVaM1JsYzNRdWIzSm5MblZyTHpBd01UVTRNREF3TURFMmFUUTBWa0ZCVVM4d01ERTFPREF3TURBeE5tazBORlpCUVZFdWFuZHJjeUlzSW05eVoxOXFkMnR6WDNKbGRtOXJaV1JmWlc1a2NHOXBiblFpT2lKb2RIUndjem92TDJ0bGVYTjBiM0psTG05d1pXNWlZVzVyYVc1bmRHVnpkQzV2Y21jdWRXc3ZNREF4TlRnd01EQXdNVFpwTkRSV1FVRlJMM0psZG05clpXUXZNREF4TlRnd01EQXdNVFpwTkRSV1FVRlJMbXAzYTNNaUxDSnpiMlowZDJGeVpWOXFkMnR6WDJWdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5clpYbHpkRzl5WlM1dmNHVnVZbUZ1YTJsdVozUmxjM1F1YjNKbkxuVnJMekF3TVRVNE1EQXdNREUyYVRRMFZrRkJVUzl0TVV4cFV6TnhURFZaTTBGdVRucHhUMnBFU0RkMExtcDNhM01pTENKemIyWjBkMkZ5WlY5cWQydHpYM0psZG05clpXUmZaVzVrY0c5cGJuUWlPaUpvZEhSd2N6b3ZMMnRsZVhOMGIzSmxMbTl3Wlc1aVlXNXJhVzVuZEdWemRDNXZjbWN1ZFdzdk1EQXhOVGd3TURBd01UWnBORFJXUVVGUkwzSmxkbTlyWldRdmJURk1hVk16Y1V3MVdUTkJiazU2Y1U5cVJFZzNkQzVxZDJ0eklpd2ljMjltZEhkaGNtVmZjRzlzYVdONVgzVnlhU0k2SW1oMGRIQnpPaTh2YzNSaGNteHBibWRpWVc1ckxtTnZiU0lzSW5OdlpuUjNZWEpsWDNSdmMxOTFjbWtpT2lKb2RIUndjem92TDNOMFlYSnNhVzVuWW1GdWF5NWpiMjBpTENKemIyWjBkMkZ5WlY5dmJsOWlaV2hoYkdaZmIyWmZiM0puSWpwdWRXeHNmUS51UDJTNzdNT1NFbFhseDdfOVE3U0h2QlpXbVVCVEsyaV90LWZoYkN0eHpsUWM0V281NXJ5RmVwQXpSNU45ejl6LU81WV9oMUZtTzAtUE5PaURJbHE3QllWYlpwb3pXTkJfLWlwSGJIcF9FZ1M0UFNmUDRsVFBHMS1SMVgyMFdoMDZMSThvVjVlYjlDSlNHWnhUYTBURFRvVE53ZVZtMF9XSkFvdVRCZWhaMFdjeXRKcUtiN0JzOVNMcjhrclhBWHpKd2VPNjBJOXRPOTlHQXlSS0ZPekFwd1pXZ1ctdGc2Q3BwZEk4M21kbHE1SUdjVmNqbU5Cb1BXUnFVUWFCVlFyZUlJaWM4VU9yYXl4WjlUckl5d0dXN0JZQkhnQmxEbzA4N3g1TFE3dzlXYklsRHpIelpKYUtOUVZwZmZxcHJCQkZkb1BYZHdXWHZoVDh2OHJXdURxLUEiLCJzY29wZSI6Im9wZW5pZCBhY2NvdW50cyBwYXltZW50cyIsInJlcXVlc3Rfb2JqZWN0X3NpZ25pbmdfYWxnIjoiUFMyNTYiLCJleHAiOjE3MDYwMjg0MTIsImlhdCI6MTcwNjAyNzgxMiwianRpIjoiOTM4YmFmZjgtYjc4NC00MTQyLTkwODItMjk3MDhhODU2OTI5IiwicmVzcG9uc2VfdHlwZXMiOlsiY29kZSBpZF90b2tlbiJdLCJpZF90b2tlbl9zaWduZWRfcmVzcG9uc2VfYWxnIjoiUFMyNTYifQ.w6r4rCWs0TycXrdWTV1IstaWdSTEmC6ge8kjeM3m_C6QDencmme5OvRQLjEZVLd6QRe50C-DH0KvsoYxnnEjZfWTdHZj9Fki6fumDCMBkbccvSjDauSus4cQS9JPIK0HP7ILbFiyeCGaSuu-hoxPUxylel4Fp23YHVHrSc5Dtm0LvSB2AgxRYZAlOPM0CXLJE_nZwRpnMc_obZrPQXGBYzhGdHMdVWh7RgC3zqmDYbOLsby9iG2HbWMpt49iMLiOT60Un5uJ2Ja9znkHCmy77dsjSLOfVjiqfd4J2dsgSLzjrDPHfCjFPzaOizktwDRpMyXKwcf9FrZTo6hZoUA5jw
The jose header is generally sent as a detached http header with the body stripped out. The payload is sent as the raw http body (and is vanilla json).
eyJhbGciOiJQUzI1NiIsImtpZCI6ImVJMVlEX3pzZlREaWJJM3lod3NsYlA1VUdPYyIsImh0dHA6Ly9vcGVuYmFua2luZy5vcmcudWsvaWF0IjoxNzA2MDI4NDY3LCJodHRwOi8vb3BlbmJhbmtpbmcub3JnLnVrL2lzcyI6IjAwMTU4MDAwMDE2aTQ0VkFBUS9tMUxpUzNxTDVZM0FuTnpxT2pESDd0IiwiaHR0cDovL29wZW5iYW5raW5nLm9yZy51ay90YW4iOiJvcGVuYmFua2luZy5vcmcudWsiLCJjcml0IjpbImh0dHA6Ly9vcGVuYmFua2luZy5vcmcudWsvaWF0IiwiaHR0cDovL29wZW5iYW5raW5nLm9yZy51ay9pc3MiLCJodHRwOi8vb3BlbmJhbmtpbmcub3JnLnVrL3RhbiJdfQ..UQI4xzvZlxUJGg_yq-QZicNjux9m4J61whEte9ZRPFaKVi-vtfphkh3fQ1olH_FLmYM5Ii-fF59cKjv7GGi1F73ArJH6D7J1GbAey3nIztl07wVh0nD-VatZCYqtpPyQ_a4Woqjrnfe4E1u0VuvDh9AtIROiwda1uz0H_M1ZlC2uPGKvjxbOqu54vADgfB1FaVsV4xSs4yfh3AEyzadC7rOjgB8aOESMj7kn_ylUyE4RTPaAS2RC_FOVauZOghByjLf4xGElIY6MSCVVP2-8xttxaumpl7MYiM4Uz447ZK3qVrtHGQKw_yt_LOaRRuyWS_RhD8Eh_FeWrTy2QZK1qw
from jjwt.
Do you have an example with the cty
value set?
from jjwt.
Do you have an example with the cty value set?
eyJraWQiOiJlSTFZRF96c2ZURGliSTN5aHdzbGJQNVVHT2MiLCJjdHkiOiJqc29uIiwidHlwIjoiSldUIiwiYWxnIjoiUFMyNTYifQ.eyJncmFudF90eXBlcyI6WyJjbGllbnRfY3JlZGVudGlhbHMiLCJhdXRob3JpemF0aW9uX2NvZGUiLCJyZWZyZXNoX3Rva2VuIl0sImFwcGxpY2F0aW9uX3R5cGUiOiJ3ZWIiLCJpc3MiOiJtMUxpUzNxTDVZM0FuTnpxT2pESDd0IiwidGxzX2NsaWVudF9hdXRoX3N1YmplY3RfZG4iOiJDTj0wMDE1ODAwMDAxNmk0NFZBQVEsMi41LjQuOTc9UFNER0ItRkNBLTczMDE2NixPPVN0YXJsaW5nIEJhbmsgTGltaXRlZCxDPUdCIiwicmVkaXJlY3RfdXJpcyI6WyJodHRwczovL3RlYXBvdHByb2R1Y3Rpb25zLnRlc3QvcmVkaXJlY3QxL2Zsb3ciXSwidG9rZW5fZW5kcG9pbnRfYXV0aF9tZXRob2QiOiJ0bHNfY2xpZW50X2F1dGgiLCJhdWQiOiIwMDE1ODAwMDAxNmk0NFZBQVEiLCJzb2Z0d2FyZV9pZCI6Im0xTGlTM3FMNVkzQW5OenFPakRIN3QiLCJzb2Z0d2FyZV9zdGF0ZW1lbnQiOiJleUpoYkdjaU9pSlFVekkxTmlJc0ltdHBaQ0k2SWtWalNFUllhV2xtVFZsWmIwRnpNRUZQWjJsdmJXOTJhMHd3YzBwa2RVRk1lRmx3VTFNM1pUbFBWVms5SWl3aWRIbHdJam9pU2xkVUluMC5leUpwYzNNaU9pSlBjR1Z1UW1GdWEybHVaeUJNZEdRaUxDSnBZWFFpT2pFM01EWXdPVEF3TURJc0ltcDBhU0k2SWpNME1HWmxNbVEyTW1JME1EUTBNakFpTENKemIyWjBkMkZ5WlY5bGJuWnBjbTl1YldWdWRDSTZJbk5oYm1SaWIzZ2lMQ0p6YjJaMGQyRnlaVjl0YjJSbElqb2lWR1Z6ZENJc0luTnZablIzWVhKbFgybGtJam9pYlRGTWFWTXpjVXcxV1ROQmJrNTZjVTlxUkVnM2RDSXNJbk52Wm5SM1lYSmxYMk5zYVdWdWRGOXBaQ0k2SW0weFRHbFRNM0ZNTlZrelFXNU9lbkZQYWtSSU4zUWlMQ0p6YjJaMGQyRnlaVjlqYkdsbGJuUmZibUZ0WlNJNklrUmxiVzh2YzJGdVpHSnZlQ0JwYm5SbGNtNWhiQ0IwWlhOMGFXNW5JaXdpYzI5bWRIZGhjbVZmWTJ4cFpXNTBYMlJsYzJOeWFYQjBhVzl1SWpvaVQyNXNlU0IxYzJWa0lHbHVkR1Z5Ym1Gc2JIa3VJaXdpYzI5bWRIZGhjbVZmZG1WeWMybHZiaUk2SWpBdU1TSXNJbk52Wm5SM1lYSmxYMk5zYVdWdWRGOTFjbWtpT2lKb2RIUndjem92TDNOMFlYSnNhVzVuWW1GdWF5NWpiMjBpTENKemIyWjBkMkZ5WlY5eVpXUnBjbVZqZEY5MWNtbHpJanBiSW1oMGRIQnpPaTh2YzNSaGNteHBibWRpWVc1ckxtTnZiU0lzSW1oMGRIQnpPaTh2ZEdWaGNHOTBjSEp2WkhWamRHbHZibk11ZEdWemRDSXNJbWgwZEhCek9pOHZkR1ZoY0c5MGNISnZaSFZqZEdsdmJuTXVkR1Z6ZEM5eVpXUnBjbVZqZERFdlpteHZkeUpkTENKemIyWjBkMkZ5WlY5eWIyeGxjeUk2V3lKUVNWTlFJaXdpUVVsVFVDSmRMQ0p2Y21kaGJtbHpZWFJwYjI1ZlkyOXRjR1YwWlc1MFgyRjFkR2h2Y21sMGVWOWpiR0ZwYlhNaU9uc2lZWFYwYUc5eWFYUjVYMmxrSWpvaVJrTkJSMEpTSWl3aWNtVm5hWE4wY21GMGFXOXVYMmxrSWpvaU56TXdNVFkySWl3aWMzUmhkSFZ6SWpvaVFXTjBhWFpsSWl3aVlYVjBhRzl5YVhOaGRHbHZibk1pT2x0N0ltMWxiV0psY2w5emRHRjBaU0k2SWtkQ0lpd2ljbTlzWlhNaU9sc2lRVWxUVUNJc0lrRlRVRk5RSWl3aVVFbFRVQ0pkZlN4N0ltMWxiV0psY2w5emRHRjBaU0k2SWtsRklpd2ljbTlzWlhNaU9sc2lVRWxUVUNJc0lrRkpVMUFpTENKQlUxQlRVQ0pkZlN4N0ltMWxiV0psY2w5emRHRjBaU0k2SWs1TUlpd2ljbTlzWlhNaU9sc2lRVWxUVUNJc0lsQkpVMUFpTENKQlUxQlRVQ0pkZlYxOUxDSnpiMlowZDJGeVpWOXNiMmR2WDNWeWFTSTZJbWgwZEhCek9pOHZjM1JoY214cGJtZGlZVzVyTG1OdmJTSXNJbTl5WjE5emRHRjBkWE1pT2lKQlkzUnBkbVVpTENKdmNtZGZhV1FpT2lJd01ERTFPREF3TURBeE5tazBORlpCUVZFaUxDSnZjbWRmYm1GdFpTSTZJbE4wWVhKc2FXNW5JRUpoYm1zZ1RHbHRhWFJsWkNJc0ltOXlaMTlqYjI1MFlXTjBjeUk2VzNzaWJtRnRaU0k2SWxSbFkyaHVhV05oYkNJc0ltVnRZV2xzSWpvaVpHVjJaV3h2Y0dWeVFITjBZWEpzYVc1blltRnVheTVqYjIwaUxDSndhRzl1WlNJNklpczBOREl3SURNNE5UY2dOemN4T1NJc0luUjVjR1VpT2lKVVpXTm9ibWxqWVd3aWZTeDdJbTVoYldVaU9pSkNkWE5wYm1WemN5SXNJbVZ0WVdsc0lqb2lhR1ZzY0VCemRHRnliR2x1WjJKaGJtc3VZMjl0SWl3aWNHaHZibVVpT2lJck5EUXlNQ0F6T0RVM0lEYzNNVGtpTENKMGVYQmxJam9pUW5WemFXNWxjM01pZlYwc0ltOXlaMTlxZDJ0elgyVnVaSEJ2YVc1MElqb2lhSFIwY0hNNkx5OXJaWGx6ZEc5eVpTNXZjR1Z1WW1GdWEybHVaM1JsYzNRdWIzSm5MblZyTHpBd01UVTRNREF3TURFMmFUUTBWa0ZCVVM4d01ERTFPREF3TURBeE5tazBORlpCUVZFdWFuZHJjeUlzSW05eVoxOXFkMnR6WDNKbGRtOXJaV1JmWlc1a2NHOXBiblFpT2lKb2RIUndjem92TDJ0bGVYTjBiM0psTG05d1pXNWlZVzVyYVc1bmRHVnpkQzV2Y21jdWRXc3ZNREF4TlRnd01EQXdNVFpwTkRSV1FVRlJMM0psZG05clpXUXZNREF4TlRnd01EQXdNVFpwTkRSV1FVRlJMbXAzYTNNaUxDSnpiMlowZDJGeVpWOXFkMnR6WDJWdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5clpYbHpkRzl5WlM1dmNHVnVZbUZ1YTJsdVozUmxjM1F1YjNKbkxuVnJMekF3TVRVNE1EQXdNREUyYVRRMFZrRkJVUzl0TVV4cFV6TnhURFZaTTBGdVRucHhUMnBFU0RkMExtcDNhM01pTENKemIyWjBkMkZ5WlY5cWQydHpYM0psZG05clpXUmZaVzVrY0c5cGJuUWlPaUpvZEhSd2N6b3ZMMnRsZVhOMGIzSmxMbTl3Wlc1aVlXNXJhVzVuZEdWemRDNXZjbWN1ZFdzdk1EQXhOVGd3TURBd01UWnBORFJXUVVGUkwzSmxkbTlyWldRdmJURk1hVk16Y1V3MVdUTkJiazU2Y1U5cVJFZzNkQzVxZDJ0eklpd2ljMjltZEhkaGNtVmZjRzlzYVdONVgzVnlhU0k2SW1oMGRIQnpPaTh2YzNSaGNteHBibWRpWVc1ckxtTnZiU0lzSW5OdlpuUjNZWEpsWDNSdmMxOTFjbWtpT2lKb2RIUndjem92TDNOMFlYSnNhVzVuWW1GdWF5NWpiMjBpTENKemIyWjBkMkZ5WlY5dmJsOWlaV2hoYkdaZmIyWmZiM0puSWpwdWRXeHNmUS5LYlF1am1oU0xsQ1dYUWNZMGU5c29UY2NDNHBqRDYwVk01UWd6UVBmYmJFMU5WV3hVU084am9sekYtc1Z1OU0xZ0pLcm14T3hPMVFqMTBjX1V4UWpNenJnQVQ1OHVFNEZBRXUzVlZnY0hxcXVzVTY0RzZUOGxPQXdmS1JndENpSDJVVnYxY3pwaTJYTE52MWxjSmt6akRUZXUwWkhGcndDTzMyVFdiUTZub2Qycl95aEp2cUh4a0VBRTM3dTlPUjBOVl96Tk43d20xVmZpeWh0UzJmcDNDZ3QtVjRYemZSajk3SENjY0ItUWVvektFeVp2S3pxV2xuTC00U3JvVzdIOHFfVS1UYTZrRXZ1TWdRczJrelI4eWc2Y2NXakw1emgxT2JzTm1OWTVpcnB0d3I4R2xpbGZLUlh6dVpkYmluM003M09YRVJoYi1BMzV1YmMyWjNxaVEiLCJzY29wZSI6Im9wZW5pZCBhY2NvdW50cyBwYXltZW50cyIsInJlcXVlc3Rfb2JqZWN0X3NpZ25pbmdfYWxnIjoiUFMyNTYiLCJleHAiOjE3MDYwOTA2MDIsImlhdCI6MTcwNjA5MDAwMiwianRpIjoiMGIyZDA2OTEtZDQ1MC00NzAwLWJlNGYtYzFiYTgzZTMwMGVkIiwicmVzcG9uc2VfdHlwZXMiOlsiY29kZSBpZF90b2tlbiJdLCJpZF90b2tlbl9zaWduZWRfcmVzcG9uc2VfYWxnIjoiUFMyNTYifQ.MODepc6rfSy174yAmrmd_eOwvPE0Hp4iSYNxB6bSPQIl9odpybmUFxpX5stfgO6ERqIMyxhv3jaafzmb4Oq_r0kG587GforAmak28nMYAt6xLYh1LTrGAWVkS3AMe75cofZ06Tr2BP2wsK70VCqGN2qLuFKJqcBamOGahPR3SjSHGvlPyJE7KQNm7FHXkYsHI7OlFiPHWNv0GDrS_bCGYNCVacYTJsjLT8_bcPYtMuLHBlEwMpLrz7ONFMLXdR4C7swsbHoBCCaN9tB8PTuHEP9UJ6ijybG66IpgjW8kGw-LyIK_lUwyvvIdtDSVBdEyoOhvGoypYTpEQjHBiTBJ4Q
from jjwt.
Related Issues (20)
- package jjwt is not resolved HOT 4
- Locator for Key has no access to JWT claims (issuer) HOT 1
- Error building JWT with non-string audience claim type HOT 4
- A single audience value gets converted into a set with one entry HOT 1
- Disable Jackson ObjectMapper FAIL_ON_UNKNOWN_PROPERTIES Deserialization Feature HOT 1
- Question: How far is version 1.0 (due to breaking changes in 0.12)?
- NIST Elliptic Curve JWK field element octet string padding HOT 1
- Allow parsing signed JWTs without the key HOT 1
- Impossible to build a JWK with `alg: HS512` and a `k` that is larger than 64 bytes HOT 2
- Make JacksonDeserializer constructor public
- Unable to access jcaName from Jwts.SIG HOT 2
- Jwts.builder - audience cannot be add without calling add() HOT 5
- Consider a convenience method to obtain a `Jwk` from a `JwkSet` by Key ID HOT 4
- Deprecation of support for unsecured JWT token parsing with algo != 'none' HOT 3
- NoSuchMethodError when using libraries built against older jjwt version HOT 2
- Unable to verify Elliptic Curve signature using configured ECPublicKey. Invalid encoding for signature HOT 2
- CVE reported against 0.11.5 HOT 5
- CVE-2024-31033 (v0.12.5) HOT 2
- java.lang.IllegalArgumentException: Invalid Map 'iv' (Initialization Vector) value: 1230868678. Values must be either String or [B instances. Value type found: java.math.BigInteger. HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jjwt.