Describe the bug
Returning any failure in a OAuth2TokenValidator validate function always results in a InvalidBearerTokenException with the error code BearerTokenErrorCodes.INVALID_TOKEN and returns a 401. The Error handling does not respect the Error code the validate function returns. This leads to OAuth2ErrorCodes.INVALID_REQUEST get converted to BearerTokenErrorCodes.INVALID_TOKEN.
To Reproduce
Return OAuth2ErrorCodes.INVALID_REQUEST in OAuth2TokenValidator validate. This was already the case in an bug I reported earlier: https://github.com/spring-projects/spring-security/issues/10319
Expected behavior
If I return OAuth2ErrorCodes.INVALID_REQUEST failure from OAuth2TokenValidator validate I expect an OAuth2AuthenticationException with the BeareErrorCode BearerTokenErrorCodes.INVALID_REQUEST and the status code 400.
Sample The problematic line in the sourcode is the following https://github.com/spring-projects/spring-security/blob/8c74d6cea5836def47102dfa7f3b7687992f95aa/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java#L101
Each BadJwtException is converted to InvalidBearerTokenException with the error code BearerTokenErrorCodes.INVALID_TOKEN
Comment From: jzheaux
Hi, @jason076, thanks for the report.
If I return
OAuth2ErrorCodes.INVALID_REQUESTfailure fromOAuth2TokenValidatorvalidate I expect anOAuth2AuthenticationExceptionwith theBeareErrorCode BearerTokenErrorCodes.INVALID_TOKEN
Why would you want the error to change? The errors are defined as follows (emphasis mine):
invalid_request The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed. The resource server SHOULD respond with the HTTP 400 (Bad Request) status code.
invalid_token The access token provided is expired, revoked, malformed, or invalid for other reasons. The resource SHOULD respond with the HTTP 401 (Unauthorized) status code. The client MAY request a new access token and retry the protected resource request.
So I'm not sure why you'd want to return an invalid_request when the token is invalid.
and the status code 400.
The above says that invalid_token should yield a 401 and invalid_request should yield a 400. Because of that, I don't think we want to send invalid_token with a 400 by default.
I believe you can customize the behavior in your own BearerTokenAuthenticationEntryPoint.
Have I misunderstood your use case?
Comment From: jason076
Sorry, I had a Mistake in the expected behavior section. I will correct my post. Here is the correct version:
** Expected behavior ** If I return OAuth2ErrorCodes.INVALID_REQUEST failure from OAuth2TokenValidator validate I expect an OAuth2AuthenticationException with the BearerErrorCode BearerTokenErrorCodes.INVALID_REQUEST and the status code 400.
** Background **
Earlier I reported that an expired token lead to an OAuth2ErrorCodes.INVALID_REQUEST failure. https://github.com/spring-projects/spring-security/issues/10319
In our project I wondered why the server is returning 401 despite this bug. I expected that if a OAuth2TokenValidator returns OAuth2ErrorCodes.INVALID_REQUEST the server would return 400. So I debuged the code and found that in line https://github.com/spring-projects/spring-security/blob/8c74d6cea5836def47102dfa7f3b7687992f95aa/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtAuthenticationProvider.java#L101
the INVALID_REQUEST is turned into an INVALID_TOKEN effectively changing the status from 400 to 401.
Comment From: jason076
So in short the current code does the following OAuth2TokenValidator.validate() returns OAuth2ErrorCodes.INVALID_REQUEST but the server response is BearerTokenErrorCodes.INVALID_TOKEN 401. So i think it is a bug. It should be 400 for INVALID_REQUEST.
Comment From: jzheaux
Ah, gotcha, @jason076. Thanks for clarifying.
It seems to me that if the validator determines the token to be invalid, an INVALID_TOKEN should be returned. If the validator is returning an INVALID_REQUEST then, I'd expect the validator's behavior to be corrected.
Taking a look at JwtClaimValidator, I think it incorrectly returns INVALID_REQUEST.
Can you submit a PR to correct JwtClaimValidator, or can you explain why validators should return an INVALID_REQUEST?
Comment From: spring-projects-issues
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.
Comment From: spring-projects-issues
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.
Comment From: jason076
Sorry for the late Feedback. I will submit a PR in the next days.
Comment From: jason076
I have submitted the PR #10500