The issue is asked on stackoverflow https://stackoverflow.com/questions/77664281/spring-security-oauth2-authentication-always-to-the-failureurl-after-token-reque but there is no answer. I am not sure if it is a known issue or I have missed something in my code.
I work on a web application project using the following version to integrate MS EntraID oauth2 authentication. It is not a Spring Boot project so I can't use MS provided Spring Cloud Azure AD.
- Spring Framework 5.3.20
- Spring Security 5.7.1 (with OAuth2 dependency sping-security-oauth2-client, spring-security-oauth2-core, spring-security-oauth2-jose)
- Tomcat 9
I use the following Java config and I can see that the oauth2 authorization code is got successfully but after the /token request (with the authorization code) is successful, the application always goes to the configured failureUrl.
To Reproduce, use the Java configuration (listed below) and kick off a MS EntraID authentication, enter username and password on the MS login page, then the application goes to the configured failureUrl. From the DEBUG log, it shows the authorization code is received successfully but after the authentication token request, it is redirected to the failureUrl.
2023-12-15 09:45:14.360 [http-nio-8080-exec-2] DEBUG RestTemplate:147 - Response 200 OK 2023-12-15 09:45:14.361 [http-nio-8080-exec-2] DEBUG RestTemplate:147 - Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json;charset=utf-8" 2023-12-15 09:45:14.381 [http-nio-8080-exec-2] DEBUG DefaultRedirectStrategy:57 - Redirecting to /myapp/oauth2login.jsp?login-error=true
I use the scope=openid as required by the MS EntraID and tried both v1 and v2 endpoint for the test. authorization-uri=https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/authorize token-uri=https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token
Expected behavior, once the access token request is successful, it would retrieve the access token and go to he configured defaultSuccessUrl. According to MS document, the POST /token request requires grant_type/code/client_id/redirect_uri/client_secret https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-access-token-with-a-client_secret With the spring security DEBUG log below, I could only see grant_type/code/redirect_uri in the /token request. However, the response is 200 OK. I am not sure if the log hides some parameters in the POST request body.
The Java config is located at https://gist.github.com/qch1866/f9aa38357a3c3674ba3ee640a43746f1
The Spring Security debug log is located at https://gist.github.com/qch1866/2b953a5b43b0bf3ec3e81ddecea69f8b
Comment From: krezovic
From the configuration you see, it's likely your authentication provider is OidcAuthorizationCodeAuthenticationProvider. You have required dependency 'spring-security-oauth2-jose'. Info extracted from
https://github.com/spring-projects/spring-security/blob/main/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java#L377
If you examine the code https://github.com/spring-projects/spring-security/blob/main/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcAuthorizationCodeAuthenticationProvider.java
The first issue you'll end up is missing JWKS URL, as the default verification algorithm is RSA256 and ID Token Decoder Factory that ends up being called is
https://github.com/spring-projects/spring-security/blob/main/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java#L159
Comment From: qch1866
Many thanks for the reply and the information can help me understand more on the Spring Security code.
I found the reason after debugging into the code. Firstly, I need to customize the /token request for EntraID, the default request seems not include the clientId/clientSecret required by EntraID. I verified the customized /token request with Postman.
However, in my application, it still redirects me to the failureUrl with the customized /token request. The debug log shows the /token response is 200 and no other errors. The debugging into the code shows me the /token response body is null and headers are good. One post on stackoverflow reminds me that the null body may be related to Json parsing. I went back to check my Json dependency and found there are two versions of Gson.jar files in my lib directory. The issue is fixed after I remove the old version Gson.jar. The response body can be parsed and I can retrieve the access_token and id_token.
You are right, after I get the id_token successfully, I can see errors from the Spring security debug log that complains the JWKS URL config missing. I add the JWKS URL config on ClientRgistration to solve the issue.
I am not sure if it is better to add a debug log info when body parsing has problem (or maybe Json parsing doesn't belong to Spring Security, in which case Spring Security may add some additional checking for the null body). When body is null, the parsed Map
The issue is not a bug and may be closed. Many thanks for your help!
Comment From: krezovic
Further information about response conversion can be found at
https://github.com/spring-projects/spring-security/blob/main/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/OAuth2AccessTokenResponseHttpMessageConverter.java
It prefers converters in the following order:
- Jackson2
- GSON
- JSONB
See also: https://github.com/spring-projects/spring-security/blob/main/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/http/converter/HttpMessageConverters.java
As you are the original poster, you can close the task yourself.
Comment From: qch1866
Issue is closed as it is not a bug.
Comment From: makarandparab
Hi
I am also facing the same issue but not able to resolve. Can you please share your code so that i can check if there is a configuration issue or issue with spring version.
Comment From: qch1866
The code is located at Github from the first post. Your issue may be not the same as mine.
- Turn on Spring Security Trace level log to get more information
- If you use OAuth2 authorization code flow, check your failure is from the authorize stage or token stage. You may use Postman to verify your request (you may see the requests in Trace level log)
Comment From: makarandparab
The code is located at Github from the first post. Your issue may be not the same as mine.
- Turn on Spring Security Trace level log to get more information
- If you use OAuth2 authorization code flow, check your failure is from the authorize stage or token stage. You may use Postman to verify your request (you may see the requests in Trace level log)
Thanks for responding.
Got the blocker removed. Problem with scopes at my end which was causing the issue.