-
Notifications
You must be signed in to change notification settings - Fork 6k
OpenID Connect: Make OAuth2AuthorizationRequest for IDToken validation #8342
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
Comments
@furti The recommended way is to plug in a custom Can you provide me more details on your custom validation logic. For example, what are the |
Lets assume a Client has different protected resources. Some resources are permitted for username and password authentication, and others are only permitted with Multifactor Authentication.
For this I already created a custom private OAuth2AuthorizationRequest resolve(HttpServletRequest request,
OAuth2AuthorizationRequest authorizationRequest)
{
if (authorizationRequest == null)
{
return null;
}
Map<String, Object> additionalParameters = new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
Map<String, Object> attributes = new LinkedHashMap<>(authorizationRequest.getAttributes());
addRequestedAcrParameter(request, additionalParameters, attributes);
return OAuth2AuthorizationRequest
.from(authorizationRequest) //
.additionalParameters(additionalParameters)
.attributes(attributes)
.build();
}
private void addRequestedAcrParameter(HttpServletRequest request, Map<String, Object> additionalParameters,
Map<String, Object> attributes)
{
String[] acr = request.getParameterValues(ACR_PARAM);
if (acr == null)
{
return;
}
attributes.put(ACR_PARAM, Arrays.asList(acr));
additionalParameters.put("claims", buildAcrRequest(acr));
}
private String buildAcrRequest(String[] acrs)
{
String acr = Arrays.stream(acrs).collect(Collectors.joining(","));
return String.format("{\"id_token\":{\"acr\": {\"values\": [\"%s\"], \"essential\": true}}}", acr);
} Now the OpenID Connect spec says https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
For me that means, check that the Server responded with an acr value in the list of the requested acr values. But the For now I register a custom @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
Collection<String> requestedAcrValues = getRequestedAcrValues(authentication);
OAuth2LoginAuthenticationToken openIdAuthentication =
(OAuth2LoginAuthenticationToken) super.authenticate(authentication);
validateAcrValues(requestedAcrValues, openIdAuthentication);
return openIdAuthentication;
} I think this is not the most clean approach to extend validation. It also has the disadvantage of fetching the userinfo, even when the acr value is invalid, as fetching happens in the super call. |
@furti I see your dilemma. You need access to the It doesn't make sense to directly provide the The first thought that came to mind is providing a |
@furti Have you been able to figure out an alternative way to validate the |
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed. |
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue. |
Sorry for my late reply. For now I used the approach mentioned above with a custom AuthenticationProvider as it works. I also have no idea on how to solve this in a clean way. |
I'm having the same dilemma.... Several resources that require different authentication levels... |
Yeap same Problem, want some Admin resources behind higher LoA and the only hint I can find regarding this is this closed GitHub issue. |
Summary
I can't find an easy way, to validate that the acr value in the ID Token is what the client expects. The spec says, when requesting an acr claims value, the Client SHOULD check, if the acr value is appropriate.
For now, the only way I see is registering a custom AuthenticationProvider that enhances the logic of the default Authentication Provider and performs the validation afterwards.
Requesting acr claims is not supported by spring security at the moment, but it is pretty straight forward to create a custom
OAuth2AuthorizationRequestResolver
that adds the relevant data to theOAuth2AuthorizationRequest
. So the information, that a acr value was requested is stored inside theOAuth2AuthorizationRequest
.Actual Behavior
Currently the
OAuth2AuthorizationRequest
is not passed to the ID Token generation and validation logic here:spring-security/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java
Line 219 in 6d45ec5
Only the ClientRegistration is passed in.
The only place where data from the request is used to validate the ID Token ist in
spring-security/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java
Line 158 in 6d45ec5
There is no way to do additional validation of the ID Token based on data of the
OAuth2AuthorizationRequest
.Expected Behavior
It should be possible to add custom validation logic of the ID Token based on data of the
OAuth2AuthorizationRequest
.I see two possible solutions
Solution 1
Create a ID Token Validator interface and call it on line
spring-security/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java
Line 158 in 6d45ec5
And move the noce validation into a default validator implementation.
Solution 2
Enhance the JwtDecoderFactory and pass the
OAuth2AuthorizationRequest
to the factory.spring-security/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java
Line 220 in 6d45ec5
I would prefer solution 2, because a lot of ID Token Validation is already done in the decoder factory. The only thing done outside is Nonce validation. When the request is available to the factory, the nonce validation could be moved inside.
The factory is already pluggable. So its easy to customize and add additional validations when needed.
Version
5.2.3 -> Still in latest master
The text was updated successfully, but these errors were encountered: