11

Using Spring Security 5 oauth I successfully ran through the whole authentication/authorization cycle using Google as OAuth provider, but I am stuck if I use an OAuth provider that I made myself, running on a different application.

I'm using the following 2 dependencies:

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>

Using Google, I just configured this:

spring.security.oauth2.client.registration.google.client-id=xxx
spring.security.oauth2.client.registration.google.client-secret=xxx

When using Google (or Facebook, Github or Okta), there is a default configuration that takes care of other settings.

Now I created my own OAuth provider. This is also a Spring Boot application configured with @EnableAuthorizationServer and otherwise fairly standard, though it has custom principals. This is also running on localhost but port 8081. The configuration in the resource server is as such:

spring.security.oauth2.client.registration.bx.client-id=xxx
spring.security.oauth2.client.registration.bx.client-secret=xxx
spring.security.oauth2.client.registration.bx.client-name=bx
spring.security.oauth2.client.registration.bx.provider=bx
spring.security.oauth2.client.registration.bx.scope=user
spring.security.oauth2.client.registration.bx.redirect-uri-template=http://localhost:8080/login/oauth2/code/bx
spring.security.oauth2.client.registration.bx.client-authentication-method=basic
spring.security.oauth2.client.registration.bx.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.bx.authorization-uri=http://localhost:8081/oauth/authorize
spring.security.oauth2.client.provider.bx.token-uri=http://localhost:8081/oauth/token
spring.security.oauth2.client.provider.bx.user-info-uri=http://localhost:8081/oauth/userInfo
spring.security.oauth2.client.provider.bx.user-name-attribute=name

When trying to use this to log in I am properly redirected to the OAuth provider, where I can log in and allow access to the requested scope using the default generated interface:

authorize screen

After hitting authorize, I get stuck on the callback part. I can see a callback to

http://localhost:8080/login/oauth2/code/bx?code=xxx&state=xxx

coming back from the oauth server and this results in a default HTML page in Spring being shown with the information:

Your login attempt was not successful, try again.

Reason: [authorization_request_not_found]

Login with OAuth 2.0

Google

bx

The log in the resource server is quite long, but I extracted the helpful part:

19:20:07.985 [http-nio-8080-exec-9] DEBUG o.a.coyote.http11.Http11InputBuffer - Received [GET /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3463.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8081/oauth/authorize?response_type=code&client_id=brain&scope=user&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D&redirect_uri=http://localhost:8080/login/oauth2/code/bx
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: JSESSIONID=4DE280E17D7ED7969E9AF2434E8292E9

]
19:20:07.986 [http-nio-8080-exec-9] DEBUG o.a.t.u.http.Rfc6265CookieProcessor - Cookies: Parsing b[]: JSESSIONID=4DE280E17D7ED7969E9AF2434E8292E9
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.a.catalina.connector.CoyoteAdapter -  Requested cookie session id is 4DE280E17D7ED7969E9AF2434E8292E9
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.a.c.a.AuthenticatorBase - Security checking request GET /login/oauth2/code/bx
19:20:07.987 [http-nio-8080-exec-9] DEBUG org.apache.catalina.realm.RealmBase -   No applicable constraints defined
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.a.c.a.AuthenticatorBase -  Not subject to any constraint
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.b.w.s.f.OrderedRequestContextFilter - Bound request context to thread: org.apache.catalina.connector.RequestFacade@15328743
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
19:20:07.987 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 4 of 14 in additional filter chain; firing Filter: 'CorsFilter'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 5 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login/oauth2/code/bx'; against '/logout'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /login/oauth2/code/bx' doesn't match 'POST /logout
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /login/oauth2/code/bx' doesn't match 'PUT /logout
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /login/oauth2/code/bx' doesn't match 'DELETE /logout
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 6 of 14 in additional filter chain; firing Filter: 'OAuth2AuthorizationRequestRedirectFilter'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login/oauth2/code/bx'; against '/oauth2/authorization/{registrationId}'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.security.web.FilterChainProxy - /login/oauth2/code/bx?code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D at position 7 of 14 in additional filter chain; firing Filter: 'OAuth2LoginAuthenticationFilter'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login/oauth2/code/bx'; against '/login/oauth2/code/*'
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.s.s.o.c.w.OAuth2LoginAuthenticationFilter - Request is to process authentication
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.apache.tomcat.util.http.Parameters - Set encoding to UTF-8
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.apache.tomcat.util.http.Parameters - Decoding query null UTF-8
19:20:07.989 [http-nio-8080-exec-9] DEBUG o.apache.tomcat.util.http.Parameters - Start processing with input [code=7NVdAE&state=LnjR4J2NO8W26whMWU1GKm03pAaesgrtSPpiuElcJS0%3D]
19:20:07.991 [http-nio-8080-exec-9] DEBUG o.s.s.o.c.w.OAuth2LoginAuthenticationFilter - Authentication request failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found] 
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found] 
    at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:145)

... and some more stack trace that doesn't seem relevant

When looking at the source code of where the exception is being thrown, from https://github.com/spring-projects/spring-security/blob/master/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java it is showing the following code starting at line 145:

OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository.removeAuthorizationRequest(request);
        if (authorizationRequest == null) {
            OAuth2Error oauth2Error = new OAuth2Error(AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE);
            throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}

What does this message mean exactly? How could I have gotten in this state?

Or am I supposed to add a handler myself for the callback url and write custom code to obtain the actual access token? Surely the library should be handling this? Why is this case handled automatically for Google as OAuth provider?

I'm happy to provide any code/further configuration.

Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73
  • Please add logs of the service . – Pratik Shah Jun 18 '18 at 11:17
  • @PratikShah: Updated with some debug logging, thanks – Sebastiaan van den Broek Jun 18 '18 at 11:28
  • 1
    These error means , that authorization request doesn't found. authorization request is stored in session, so somehow session is not getting stored, check if you are getting any cookie in your browser, when you are clicking on the login api. – Pratik Shah Jun 18 '18 at 11:47
  • @PratikShah I see a JSESSIONID cookie in both the request and response cookies (with different values) of the login/oauth/code request, not sure what that means. – Sebastiaan van den Broek Jun 18 '18 at 11:59
  • 1
    I think that might be because you are running everything on localhost, so first cookie is set by localhost:8080 to store the authorization request session data, & when you login to localhost:8081 it'll set another cookie for it's session. check if the second cookie is coming from your auth server ? – Pratik Shah Jun 18 '18 at 12:03
  • Brilliant! I added an alternative name for localhost to my hosts file and configured the callback url as such and then it still doesn't work but I do get further in the process, with an exception "org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_user_info_response] An error occurred parsing the UserInfo Error response: WWW-Authenticate scheme must be OAuth 2.0 Bearer", but I'll try to figure out what that is about as well :) thanks, if you want to put this in an answer I'll accept it. – Sebastiaan van den Broek Jun 18 '18 at 12:12

6 Answers6

14

These error means , that authorization request doesn't found. authorization request is stored in session, so some how session is not getting stored. by default session is managed by cookie.

So I think that might be because you are running everything on localhost, so first cookie is set by localhost:8080 to store the authorization request session data, & when you login to localhost:8081 it'll set another cookie for it's session.

Pratik Shah
  • 1,782
  • 1
  • 15
  • 33
  • 3
    In my case it was `server.servlet.session.timeout` in my config that was explicitly set to `1m` (one minute) for testing purposes. When I hadn't finished sign-in on OAuth server's login page in 1m, then application session become invalid, and because authorization request is stored in the session, it was not found after redirecting back to the application from OAuth server! – Ruslan Stelmachenko Sep 15 '19 at 02:06
  • It was due to session getting ended, when I pressed back button (from a previous error page) and tried to select the gmail account on popup page. When I hit the auth API from beginning, it worked smoothly. – Mrityunjaya Apr 07 '20 at 16:58
  • In a load balanced environment without distributed sessions, it could mean that the user came back to a different box than the one where the session originated. Depends on how load balancing is setup. In this case, the user MUST stick to the same box. – Jim Kennedy Mar 03 '23 at 14:34
4

I have the same issue like you. After I researched this problem i found the answer on https://github.com/spring-projects/spring-security/issues/5946. The only thing you need is config you hosts file. Here is my config. I'm using Windows:

*127.0.0.1 localhost auth-server*

May be it's helpful.

Vu Tran
  • 41
  • 1
  • 5
3

You can also get this message if your running on Kubernetes or behind a Loadbalancer and forget to activate "sticky sessions" so that your requests end up on different hosts.

lathspell
  • 3,040
  • 1
  • 30
  • 49
3

I had the same error but not in a local context but with a real network context. The problem was that the application server nginx had the rule SameSite=Strict; This broke the redirection process of the oauth authorization code flow. This is well explained here even if, in this case, this is not the spring security library which is involved.

Fabrice
  • 61
  • 3
1

I was able to fix this by forcing a session to be created on the endpoint that redirects to the oauth2 jose flow. Spring's default session creation policy is "if required". My theory was that it was redirecting to the openId flows without first creating a session.

         http.authorizeRequests()
            .mvcMatchers("/<yourProvider>/login")
                .authenticated()
                .anyRequest()
                .permitAll()
                .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                .and()
            ...

If anyone has any better ideas or solutions please comment or post.

Our client is configured to go to the /yourProvider/login in order to authorize.

TheJeff
  • 3,665
  • 34
  • 52
0

I got the same error but the problem was not session but wrongly configured "user-attribute-name".

Analysis steps

  • After checking server logs I found username not found (or something similar) error.
  • I copied generated access token to the online decryptor (https://jwt.io/) and saw, that my user attribute name is not user or name but user_name.
  • Added that to spring.security.oauth2.provider..user_name_attribure

Everything began to work.

elrado
  • 4,960
  • 1
  • 17
  • 15