I am adding oauth into an application and I'm running into the following error:
[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized: [no body]
The project has a Spring Boot backend and an Eclipse rcp frontend. I'm attempting to authenticate using azure active directory as an authorization server. So far, I'm able to launch a browser widget in on startup of the eclipse application and successfully complete the authorization code request by pointing the browser to http://localhost:8080/oauth2/authorization/azure. After completing the authorization code request, the browser gets redirected to http://localhost:8080/login?error and displays the error above.
Dependencies from pom.xml
Built using spring boot with the following relevant dependencies:
spring-boot-starter-web
v2.2.4azure-active-directory-spring-boot-starter
v2.2.1spring-security-oauth2-client
v5.2.1spring-security-oauth2-jose
v5.2.1spring-security-oauth2-resource-server
v5.2.1
Config from application.yml
We support multiple authorization servers, here is the fully configured azure client:
spring:
security:
oauth2:
client:
azure:
client-id: XXX
client-secret: XXX
client-name: Microsoft
scope: openid, https://graph.microsoft.com/user.read, profile
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/azure
client-authentication-method: basic
authentication-method: post
provider:
authorization-uri: https://login.microsoftonline.com/XXX/oauth2/v2.0/authorize
token-uri: https://login.microsoftonline.com/XXX/oauth2/v2.0/token
user-info-uri: https://graph.microsoft.com/oidc/userinfo
jwt-set-uri: https://login.microsoftonline.com/dXXX/discovery/v2.0/keys
azure:
activedirectory:
tenant-id: XXX
active-directory-groups: XXX
allow-telemetry: false
websecurityconfig.java
@Configuration
@EnableConfigurationProperties
@EnableWebSecurity
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
[...]
.anyRequest().authenticated()
.and()
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.oauth2Login();
}
[...]
}
Spring logs
Here is the complete stack trace from the moment I attempt to authenticate with my azure AD user credentials (shortened to fit body length requirements & with the authorization code censored ofc):
2020-02-19 16:10:33.925 DEBUG 19564 --- [qtp148813381-16] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@2dd6e039
2020-02-19 16:10:33.925 DEBUG 19564 --- [qtp148813381-16] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-02-19 16:10:33.925 DEBUG 19564 --- [qtp148813381-16] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-02-19 16:10:33.928 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 1 of 16 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 2 of 16 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] w.c.HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: Session@3a690b15{id=node01xqnw7l82ne041bil2flqsn3vr0,x=node01xqnw7l82ne041bil2flqsn3vr0.node0,req=1,res=true}. A new one will be created.
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 3 of 16 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 4 of 16 in additional filter chain; firing Filter: 'LogoutFilter'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/oauth2/code/azure'; against '/logout'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/oauth2/code/azure' doesn't match 'POST /logout'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/oauth2/code/azure' doesn't match 'PUT /logout'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/oauth2/code/azure' doesn't match 'DELETE /logout'
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2020-02-19 16:10:33.929 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 5 of 16 in additional filter chain; firing Filter: 'OAuth2AuthorizationRequestRedirectFilter'
2020-02-19 16:10:33.930 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/oauth2/code/azure'; against '/oauth2/authorization/{registrationId}'
2020-02-19 16:10:33.930 DEBUG 19564 --- [qtp148813381-20] o.s.security.web.FilterChainProxy : /login/oauth2/code/azure?code=CODE&state=nqsFqxkkNzHJE5knQVdqFLjoPxg1MT_bcn7KzjKSFfU%3d&session_state=3ebe517e-d450-4d49-b8db-8afafe1fa37e at position 6 of 16 in additional filter chain; firing Filter: 'OAuth2LoginAuthenticationFilter'
2020-02-19 16:10:33.930 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/oauth2/code/azure'; against '/login/oauth2/code/*'
2020-02-19 16:10:33.930 DEBUG 19564 --- [qtp148813381-20] .s.o.c.w.OAuth2LoginAuthenticationFilter : Request is to process authentication
2020-02-19 16:10:33.930 DEBUG 19564 --- [qtp148813381-20] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider
2020-02-19 16:10:33.931 DEBUG 19564 --- [qtp148813381-20] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider
2020-02-19 16:10:34.273 DEBUG 19564 --- [qtp148813381-20] .s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.oauth2.core.OAuth2AuthenticationException
2020-02-19 16:10:34.275 DEBUG 19564 --- [qtp148813381-20] .s.o.c.w.OAuth2LoginAuthenticationFilter : Authentication request failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized: [no body]
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized: [no body]
at org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider.authenticate(OidcAuthorizationCodeAuthenticationProvider.java:148) ~[spring-security-o
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] .s.o.c.w.OAuth2LoginAuthenticationFilter : Updated SecurityContextHolder to contain null Authentication
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] .s.o.c.w.OAuth2LoginAuthenticationFilter : Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@2b0d857b
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] .a.SimpleUrlAuthenticationFailureHandler : Redirecting to /login?error
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] o.s.s.web.DefaultRedirectStrategy : Redirecting to '/login?error'
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@2dd6e039
2020-02-19 16:10:34.277 DEBUG 19564 --- [qtp148813381-20] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-02-19 16:10:34.278 DEBUG 19564 --- [qtp148813381-20] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
[...]
Attemps to fix this error
I have tried all the solutions from this open issue: https://github.com/microsoft/azure-spring-boot/issues/526, including enabling oauth2AllowImplicitFlow
in the azure portal manifest, to no avail.
If I print the authorization code on from the eclipse browser and create a token request to azure AD (with the azure postman collection) I get a successfull response with an bearer token.
So why am I getting a 401 Unauthorized when making my token request?
I would appreciate any suggestions on how to approach this problem. I'm desperatly looking for a solution and my next step is to try log the spring token request or inspect it with wireshark (going to have to decrypt the TLS connection since the endpoint for azure is https)
Thanks if you've read this far :)