-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Improve JWT Assertion Validation using client validators #43680
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
Conversation
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.
Unreported flaky test detected, please review
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.federation.ldap.LDAPProvidersIntegrationTest#updateLDAPUsernameTest |
|
I have changed some class names to be more appropriate. And the |
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.
Unreported flaky test detected, please review
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.federation.ldap.LDAPProvidersIntegrationTest#updateLDAPUsernameTest |
|
@rmartinc Thanks! That’s pretty much how I imagined it, and I’m ok with having the signature validation on the IdP side. |
|
I think that the |
|
Rebased with the last changes added by @graziang. 😄 |
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.
@rmartinc Cool, Thanks!
I have few inline comments (Some of them are more a questions from discussion. Feedback welcome from you and @graziang as well).
Some answers to your questions:
Do you see this OK? Or do you prefer move signature to the client validator part? Or vice-versa, move token validations to the IdP side? It's a bit repeated in both sides.
I see this OK as it is now in your PR.
The nbf claim is not checked now, I have just detected it. The client validator was not doing it before, so I will add later.
In AbstractBaseJWTValidator.validateTokenActive there is a call to token.isActive , which checks also "not before" . Is it sufficient or do we need something more?
I have added the options we have currently in the IdP side (clockSkew and algorithm), but there are other options that we can add: token lifespan (default is 5m=300s) and reusePermitted (default to false). Do we want them or is it OK using fixed values for now?
IMO ok to hardcode "reusePermitted" to false for now. There is the other PR https://github.com/keycloak/keycloak/pull/43841/files , which introduces this including proper config.
For the "token lifespan", I am not sure which token you mean? Lifespan of the assertion is handled by the attributes of JWT itself. Lifespan of the issued token is the same for "jwt-bearer" grant like for any other grants AFAIK.
|
|
||
| @Override | ||
| public String getClientAssertionSigningAlg() { | ||
| return getConfig().getClientAssertionSigningAlg(); |
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.
This effectively means that the IDP option Client assertion signature algorithm is used for both sending JWT issued by Keycloak for client authentication as well as "expected" algorithm for verification of assertions signed by the client for jwt-bearer grant.
Not 100% sure if this is good thing? Maybe it is OK for most of the cases and it is good to avoid introducing too much options. However for clients, there are different options (EG. ID Token Signature algorithm, User Info Signature algorithm), which is also prescribed in the OIDC specification.
I am like 50/50 whether to use same option or different. If we keep same option, we at least need to update the tooltip IMO.
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.
Yes, this was not even added by @graziang, I just added because it was in the base class and makes some sense. We can remove it for the moment or change the tooltip and doc to mention that this is the algorithm to sign any client or authorization grant. Whatever you prefer is OK to me.
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'm going to remove this check for now. If we think we should validate the signing alg for the JWT authorization grant we can add a new prop or change the meaning of the current option. But we can move this forward for the moment.
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.
Removed the check and the method in the interface JWTAuthorizationGrantProvider.
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.
Sounds good for now. IMO we may need to do this, but likely OK as a follow-up. Thanks!
| public BrokeredIdentityContext validateAuthorizationGrantAssertion(JWTAuthorizationGrantValidationContext context) throws IdentityBrokerException { | ||
|
|
||
| // verify signature | ||
| if (!verify(context.getJws())) { |
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.
It seems you addressed also #43644 with this PR :-) I've assigned that issue to yourself due to that.
It may be also good to remove TODO from line 1079 as I am not sure if there is something more to validate, which we are not already validating? Besides some complex stuff, which we may do with client policies (Follow-up issue for that is #43573 ) .
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.
Yes, I did it because using the IdP it was already done. 😄 I will remove the TODO if we accept this way of validating the signature.
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.
Done!
|
I have removed the TODO in the
We can manage those as a follow-up if we agree that any of those options are needed too. |
Ah, ok. Thanks for the clarification! |
@rmartinc Thanks for the summary. I agree that those should be possible to configure. I've created a follow-up issue #43873 . The "Re-use" is already added in other subsequent PR by Giuseppe for #43568 . So IMO this PR is ready to go. |
Closes keycloak#43642 Signed-off-by: rmartinc <[email protected]>
|
Rebased! |
Closes #43642
The PR creates a new intermediate class
AbstractJWTValidatorwith part of the methods that previously were inAbstractJWTClientValidator. ClassJWTAuthorizationGrantValidationContextinserver-spi-privateis now an interface (very limited now, but we can add mode methods if needed) and the real code has been moved toJWTAuthorizationJWTValidatorinserviceswhich extends theAbstractJWTValidatorto inherit the old methods. This way the code is shared. The signature validation is performed in the IdP side, and we can move more parts to the IdP if we want. So the current code is something in the middle. The token is validated using the client validator, but the signature is checked by the IdP. Draft for the moment. Questions:nbfclaim is not checked now, I have just detected it. The client validator was not doing it before, so I will add later.I need to polish this a bit but the I want to hear your comments about the three questions before. 😄