-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
smallrye-jwt-extension: Make role mapping configurable and use newer smallrye-jwt apis #7485
smallrye-jwt-extension: Make role mapping configurable and use newer smallrye-jwt apis #7485
Conversation
@andreas-eberle Thanks for this PR. I'm not sure right now about it.
The other thing I'd like to propose is to split the PR into few dedicated ones, for example, may be you could start with a PR containing only those changes which clean up the smallrye-jwt code. (Note I don't think we recommend wildcard imports and I recall @stuartwdouglas advising against using the lambdas.etc during the initialization time). |
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.
There are some interesting ideas in this PR but IMHO it needs to be split with some of those changes likely needing to go to smallrye/smallrye-jwt
@sberyozkin: I just added a new PR #7489 with the fixes for the warnings in the tests. I will have a look at the smallrye interfaces. |
76dcf59
to
db2501d
Compare
I removed the test changes from this PR to give a clearer picture of the actual changes. |
@andreas-eberle Thanks. Please also review these docs: https://github.com/quarkusio/quarkus/blob/master/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc |
@andreas-eberle May be also makes sense to make it a Draft given that it will be split going forward anyway; Hi @gsmet, @geoand I'm not not sure how to stop the PR build :-) |
It should be possible to cancel builds from the GitHub Actions UI. You may need to cancel each job separately however... |
It's no big deal, let it run. |
I opend a Zulip chat to better discuss what to do for this PR. |
I update the code to the newer smallrye-jwt apis. Unfortunately, I currently have to use the SNAPSHOT version of it since the changes of smallrye/smallrye-jwt#192 are required to be able to implement the tests. |
@andreas-eberle Right, first it needs to be released. |
|
||
@DefaultBean | ||
@ApplicationScoped | ||
public class DefaultJwtRolesMapper implements JwtRolesMapper { |
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.
What the existing smallrye.jwt properties such as groups path for example can't do that this interface will help with ?
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.
At the moment I see three use cases:
- the current implementation cannot handle JWTs like I showed in the example at the top. Sometimes tokens do not contain a groups field but contain role information in the form of other fields. In that example in the form of a boolean "admin" claim. With the
JwtRolesMapper
, I can write custom logic for my custom behavior to map the roles and then using the standard@RolesAllowed
annotation. - It might well be that I do not want to use the group names as they are used in the JWT, which I might have to work with but have no control over. Sometimes the group names in the JWT are just not what they mean in my application. In that case, I can use the
JwtRolesMapper
to map the groups to roles that make sense in my context and thus make the code more readable. - I have a case where I have to handle tokens from different issuers, all using different groups. With the
JwtRolesMapper
, I can map their groups depending on the issuer of the token and unify it to something usable in my application. Again, I don't have power over those issuers, which is why I have to make it work in my application.
@@ -0,0 +1,9 @@ | |||
package io.quarkus.smallrye.jwt.runtime.auth; |
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.
Same question, why is this interface needed ?
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.
@andreas-eberle If there is a real case where the roles info is spread across multiple claims and when the existing smallrye properties can't really help with the auto extraction of these roles, then lets consider this interface (that should live then in smallrye-jwt I guess) but having it just in case would be redundant. If you have some specific requirement/mapping case in mind then lets review, thanks
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.
The interface is there to allow for easy injection of own implementations of this roles mapping. Please also see my comment to your previous remark. I'm happy to move this interface to smallrye-swt. Should I prepare a PR?
@@ -52,25 +44,16 @@ public MpJwtValidator(JWTAuthContextInfo authContextInfo) { | |||
public CompletionStage<SecurityIdentity> authenticate(TokenAuthenticationRequest request, | |||
AuthenticationRequestContext context) { | |||
try { | |||
JwtContext jwtContext = parser.parse(request.getToken().getToken(), authContextInfo); | |||
JsonWebToken jwt = parser.parse(request.getToken().getToken()); |
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.
Why are these changes necessary ? I'd like to keep an option open to have the factory used instead of the parser so that people can plugin custom factories.
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 don't see why this should not be possible any more. People can now easily inject the JwtParser
implementation they like. And with the changes I proposed in smallrye/smallrye-jwt#194, it would also easily be possible to inject a different JWTCallerPrincipalFactory
into the DefaultJwtParser
.
@andreas-eberle I agree about a roles mapper as you have a valid case, thanks for the clarification. However there is no need IMHO for a default mapper returning groups as it is already taken care of in smallrye-jwt OOB. The other thing is that there should be no ambiguity when I know the users have asked about the custom roles mapping before, in fact may be in due time that can be supplied via MP JWT. So my proposal is to introduce this handy mapper interface in smallrye-jwt, without any default implementations and I suppose have it injected into the default principal implementation, and then make it also operational in Quarkus once smallrye-jwt-2.1.0 is out. We can even start from MP-JWT but it might make sense to experiment with it smallrye-jwt first and then submit, as was done for the builder API. Please, lets just deal with this factory <-> parser relationship later (for the record, I don't agree :-), but we can continue the conversation in the open smallrye-jwt issue). IMHO it makes sense to close this PR and return with a mapper related one first. It will be easier to deal with the factory/parser discussions as part of the dedicated issue/PR/etc. Do you agree ? |
@sberyozkin: The idea of the default mapper is to have an injectable bean handling the normal code execution. This can then be exchanged by the user by providing his own implementation of the In this implementation, the roles provided by smallrye-jwt are used in the exact same way as they have been used before. There is no overriding. In the default implementation, the code works like before. And if the user wants to map the roles with custom code (i.e. by implementing the Sure, we can move the Can you elaborate on the smallrye-jwt issue why you don't agree on the factory/injection issue, so I can try to understand your viewpoint better? I'm not sure yet if this PR should be closed. I will have to see what implementations we will come up with / can agree on. For now, I would keep it open. |
@sberyozkin: I was thinking about the
Therefore, in the interest of separation of concerns as well as the flexibility to get the original JsonWebToken injected while also mapping the groups of the jwt to application specific roles, I think the What do you think? |
@andreas-eberle, sorry for a delay,
I don't agree with this assertion. Ideally all smallrye-jwt integrators could avoid coming up with the container specific mechanics on how to do it... Of course, when really needed we can do things in Quarkus, etc. But this case does not seem to be such a case.
Are you saying that you'd like to target the case where for example a
But note I'm fine with not wiring this interface at the Thanks |
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.
@sberyozkin I let you drive that puppy home.
@@ -38,7 +38,7 @@ | |||
<smallrye-open-api.version>1.2.1</smallrye-open-api.version> | |||
<smallrye-opentracing.version>1.3.4</smallrye-opentracing.version> | |||
<smallrye-fault-tolerance.version>4.1.0</smallrye-fault-tolerance.version> | |||
<smallrye-jwt.version>2.0.13</smallrye-jwt.version> | |||
<smallrye-jwt.version>2.1.0-SNAPSHOT</smallrye-jwt.version> |
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.
Please don't merge as is, there's a SNAPSHOT version.
@gsmet I'm keeping the PR open to have a discussion at this stage as IMHO it is not possible to get it in directly right now, the mapper interface should be in smallrye-jwt |
@sberyozkin: I just had a look at this again. How would you like to integrate the RolesMapper into smallrye-jwt? Currently the quarkus extension uses the What do you think? |
Hi @andreas-eberle |
In this PR, the following has been changed:
Make JwtParser injectable. Currently, the JwtParser cannot be configured / intercepted. We have a use case where we need to verify the token depending on data in the token (e.g. if you would want to verify tokens from Google, Facebook, Github,... in your application without putting a Keycloak in between, you would need to read the issuer field). Unfortunately, the smallrye
DefaultJwtTokenParser
does not implement an interface. So I introduce an interfaceJwtParser
and provide a default bean for it directly forwarding the calls to the smallryeDefaultJwtTokenParser
.Make roles mapping injectable. Like the Eclipse MicroProfile RBAC documentation for groups states, it is very likely for an application to require a mapping of the groups used in a JWT to application specific roles. With the injectable
JwtRolesMapper
, this is now possible. Again, the default bean implementation preserves the former behavior.I'm looking forward to your input on this. I haven't yet documented the two new interfaces in the guides yet but if your general feedback is good, I'll be happy to do so.
Edit: Add example
Usage of the JwtParser in your application could look like this
Use of JwtRolesMapper could look like this
Edit 2: Remove now obsoleted infos in the text.