Add more granular options in skipping validation of JWTs
AFAICT, an "empty" JwtConsumer
(created with new JwtConsumerBuilder().build()
) will validate nothing except dates (if the claims are present).
When validating id_token_hint
s in OpenID Connect, you generally want to accept expired ID Tokens (see here and here). With the current API, you're forced to do a two-pass parse so you can get the ID Token's iat
and pass it to setEvaluationTime
.
It should be possible to somehow disable the NumericDateValidator
without skipping all validators; either by setting the evaluation time to null
(will currently throw an NPE in the validator) or with a new skipDateValidations
method.
Comments (11)
-
reporter -
repo owner Hello again Thomas,
I understand your request, in general I think, but I have to say that I have some reservations about it. It appears that most of what you're requesting is to make it easier to support the id_token_hint parameter in its various forms from OpenID Connect? In full disclosure - I'm not a big fan of id_token_hint in Connect (ya hear that @ve7jtb?). I think it's underspecified, potentially dangerous in some cases, and encourages or even demands behavior that is contradictory to the (soon to be RFC) JWT spec itself. From https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4 exp and aud are good examples of such that clearly say an expired JWT and/or a JWT that doesn't identify the recipient as an audience shouldn't be accepted (MUST be rejected). So JWTConsumer[Builder] attempts to follow the spec and at least make it somewhat difficult to do insecure things. By design, an "empty" JwtConsumer will validate against aud, exp, and nbf when they are present in the JWT - it can assume evaluation time is the current time but doesn't have a reasonable way of knowing the expected audience so one needs to be given.
Okay, I just had to clear the air with my thoughts on id_token_hint. But with all that said, I do want to make this API useful and easy to use.
For the date validation, you can currently get very very close to the same thing as a new skipDateValidations method would provide by setting the allowable clock skew to a very large number, i.e.:
new JwtConsumerBuilder().setAllowedClockSkewInSeconds(Integer.MAX_VALUE)
or have you tried that already and run into problems that I'm not anticipating?
For audience, I reluctantly see the value in providing something like a skipAudienceValidation method on the builder and will consider adding something like that. In the meantime, you should know the expected audience in an id_token_hint during an authentication request because it'll be the client_id from the request. That's not the case in logout/session management though and a two-pass validation might be needed there for now (I still believe that area of the spec needs some work though, for example). FWIW, the two-pass approach is a bit more code but shouldn't incur much/any of a performance impact as the parsing and crypto is only done once.
Given an expected subject to the JWTConsumer[Builder] is a reasonable ask for the cases you mention (and likely others). I'll add something for that. In the meantime you can create an implementation of Validator that does exactly that and give it to the builder with registerValidator(...). Or you can, of course, do a comparison yourself afterwords.
-
repo owner added the ability to validate an expected subject value with commit 5d6cecd
-
repo owner added the ability to skip the default audience validation with commit 6f5fe3f
-
reporter Thanks Brian.
I understand your reluctance to support
id_token_hint
, as I too am a bit uncomfortable with it (if it's supposed to be a secret, then it shouldn't be sent as a query-string parameter –theresponse_type=id_token
forbidsresponse_mode=query
–, plus it likely contains private data about the user – thesub
to begin with), and there's a risk of replay attacks unless the OP includes ajti
and tracks already-used ones. Thesid
from HTTP-Based Logout would be better; or maybe even better first exchange yourid_token
orsid
for a logout token. But that's not the place to discuss this.FYI, for now I used a custom
Validator
to validate the subject in theend_session_endpoint
, but did a comparison afterwards in theauthorization_endpoint
to be able to return a differenterror
(login_required
instead ofinvalid_param
, see https://bitbucket.org/openid/connect/issue/878 )I can't remember why I didn't use
setAllowedClockSkewInSeconds(Integer.MAX_VALUE)
. -
repo owner - changed title to Add more granular options in skiping validation of JWTs
-
repo owner also added the ablitity to skip all the default validation of the claims from JWT RFC 7519 with commit 47eba8e
-
repo owner - changed status to resolved
i'm gonna call this one good.
-
repo owner - changed title to Add more granular options in skipping validation of JWTs
-
repo owner 0.4.2 is now available
-
repo owner Issue
#26was marked as a duplicate of this issue. - Log in to comment
Actually, there's also a similar issue with the
aid
claim: if you don't callsetExpectedAudience
and the JWT contains anaud
claim, then you'll have an validation error. If should be possible to skip validating the audience value (ideally, you'd be able to validate the presence of anaud
claim without validating its value; it SHOULD be as easy as providing an empty list of acceptable audiences – currently, this case is even special-cased to provide a specific error message).The workaround is again to use two passes and feed the JWT's own audience into the acceptable audiences.
I think what I'm asking for is a separation between validating the JWT's "schema" (presence of claims, with the appropriate type) and verifying expected values.
Another case is validating an expected subject (could be useful when parsing the response of a UserInfo Endpoing when you asked for a JWT response; or validating the
sub
of an ID token after you re-authenticated the user –sendingid_token_hint
to the IdP–, it would be an error to receive an ID Token for another user). The current API only allows you to validate the presence and type of the claim, not its value.Should I open separate issues for these?