使用 Spring 安全 oauth,使用自定义 OAuth 提供程序,我得到 [authorization_request_not_found],我应该自己处理回调方法吗?

Using Spring security oauth, using a custom OAuth provider, I get [authorization_request_not_found], should I handle the callback method myself?

使用 Spring Security 5 oauth 我成功地 运行 通过整个 authentication/authorization 周期使用 Google 作为 OAuth 提供者,但是如果我使用 OAuth 提供者我会卡住我自己制作的,运行 在不同的应用程序上。

我正在使用以下 2 个依赖项:

        <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>

使用 Google,我刚刚配置了这个:

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

使用 Google(或 Facebook、Github 或 Okta)时,有一个默认配置负责其他设置。

现在我创建了自己的 OAuth 提供程序。这也是一个 Spring 配置了 @EnableAuthorizationServer 的引导应用程序,并且在其他方​​面相当标准,尽管它具有自定义主体。这也是本地主机上的 运行 但端口 8081。资源服务器中的配置是这样的:

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

当尝试使用它登录时,我被正确地重定向到 OAuth 提供程序,我可以在其中登录并允许使用默认生成的界面访问请求的范围:

点击授权后,卡在回调部分。我可以看到

的回调

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

从 oauth 服务器返回,这导致 Spring 中的默认 HTML 页面显示以下信息:

Your login attempt was not successful, try again.

Reason: [authorization_request_not_found]

Login with OAuth 2.0

Google

bx

资源服务器里的日志比较长,我摘录了有用的部分:

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)

...还有一些看起来不相关的堆栈跟踪

查看引发异常的源代码时,https://github.com/spring-projects/spring-security/blob/master/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2LoginAuthenticationFilter.java 从第 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());
}

这条消息到底是什么意思?我怎么会陷入这种状态?

或者我是否应该自己为回调添加一个处理程序 url 并编写自定义代码来获取实际的访问令牌?当然图书馆应该处理这个?为什么 Google 作为 OAuth 提供商会自动处理这种情况?

我很乐意提供任何 code/further 配置。

这些错误意味着,未找到授权请求。 authorization request 存储在会话中,因此某些会话未存储的方式。默认会话由 cookie 管理。

所以我认为这可能是因为你是 运行 本地主机上的所有内容,所以第一个 cookie 由 localhost:8080 设置以存储授权请求会话数据,&当你登录到 localhost:8081 它将为其会话设置另一个 cookie。

我能够通过强制在重定向到 oauth2 jose 流的端点上创建会话来解决此问题。 Spring 的默认会话创建策略是“如果需要”。我的理论是它在没有先创建会话的情况下重定向到 openId 流。

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

如果大家有更好的想法或解决方案欢迎评论或post。

我们的客户端配置为转到 /yourProvider/login 以进行授权。

我遇到了同样的错误,但问题不是会话而是错误配置的“用户属性名称”。

分析步骤

  • 检查服务器日志后,我发现用户名未找到(或类似的错误)。
  • 我将生成的访问令牌复制到在线解密器 (https://jwt.io/) 并看到,我的用户属性名称不是用户或名称而是 user_name。
  • 将其添加到 spring.security.oauth2.provider..user_name_attribure

一切正常。

如果您的 运行 在 Kubernetes 上或在负载均衡器后面并且忘记激活“粘性会话”以便您的请求最终在不同的主机上,您也会收到此消息。

我和你有同样的问题。在我研究了这个问题之后,我在 https://github.com/spring-projects/spring-security/issues/5946 上找到了答案。 您唯一需要做的就是配置 hosts 文件。 这是我的配置。我正在使用 Windows:

*127.0.0.1 localhost auth-server*

可能有用。我正在使用 Google 翻译来写答案。

我有同样的错误,但不是在本地上下文中,而是在真实的网络上下文中。问题是应用服务器 nginx 有规则 SameSite=Strict;这打破了 oauth 授权代码流的重定向过程。这很好解释 here 即使在这种情况下,这不是涉及的 spring 安全库。