Spring Security 一旦第一个访问令牌被刷新,OIDC RP发起的注销将不起作用

xghobddn  于 12个月前  发布在  Spring
关注(0)|答案(1)|浏览(144)

我正试图实现RP发起的注销中所描述的文档。
我有一个SPA,一个网关充当(BFF)和一个Spring授权服务器(灵感来自ch4mpy's sample demo)。
流程如下所示:SPA向网关的/logout发送get请求,网关隐式调用授权服务器以获取open-id-token和logout URL,然后从SPA获取响应的location header和href。
如果在我注销之前访问令牌没有更改,则一切正常。
但是在我的例子中,我为我的访问令牌配置了一个较短的生命周期,并使用刷新令牌授权类型来刷新它。当我刷新访问令牌时,我看到存储在AS中的open-id-token正在更改(属性“nonce”消失,“exp”和“iat”不相同)。

我的问题是,如果访问令牌至少刷新一次,当我调用注销时,我可以看到我收到的open-id-token是第一个生成的(带有“nonce”和第一个值“exp”和“iat”),而不是更新的。

当然,我在AS中的注销会在OidcLogoutAuthenticationProvider.authenticate中抛出一个异常,因为DB中没有匹配的open-id-token。
一些上下文:我正在使用spring-boot 3.1.4。
AS:

OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

http.cors(withDefaults())
    .getConfigurer(OAuth2AuthorizationServerConfigurer.class)
    .oidc(withDefaults());

个字符
好朋友:

http.oauth2Login(login -> {
        login.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/ui/login?success=true"));
        login.authenticationFailureHandler(new RedirectServerAuthenticationFailureHandler("/ui/login?success=fail"));
    })
    .logout(logout -> logout.logoutSuccessHandler(new CustomLogoutSuccessHandler(clientRegistrationRepository, postLogoutRedirectUri)));

x

static class CustomLogoutSuccessHandler implements ServerLogoutSuccessHandler {

    private final OidcClientInitiatedServerLogoutSuccessHandler delegate;

    public CustomLogoutSuccessHandler(ReactiveClientRegistrationRepository clientRegistrationRepository, String postLogoutRedirectUri) {
        this.delegate = new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository);
        this.delegate.setPostLogoutRedirectUri(postLogoutRedirectUri);
    }

    @Override
    public Mono<Void> onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) {
        return delegate.onLogoutSuccess(exchange, authentication)
                       .then(Mono.fromRunnable(() -> {
                           exchange.getExchange()
                                   .getResponse()
                                   .setStatusCode(HttpStatus.ACCEPTED);
                       }));
    }
}
spring:
    security:
        oauth2:
            client:
                provider:
                    spring:
                        issuer-uri: ${backend-uri}
                registration:
                    spring:
                        provider: spring
                        client-id: ${client-id}
                        client-secret: ${client-secret}
                        authorization-grant-type:
                            - authorization_code
                            - refresh_token
                        redirect-uri: ${gateway-uri}/login/oauth2/code/myoauth2
                        scope:
                            - openid
                            - profile
            resourceserver:
                jwt:
                    issuer-uri: ${backend-uri}

的一种或多种
任何帮助感激不尽。

btqmn9zl

btqmn9zl1#

ID令牌和访问令牌不是一回事。
RP发起的注销请求包含的是ID令牌,而不是访问令牌。
对于refresh_token流,必须在初始authorization_code流中请求offline_access作用域。对于要使用其他令牌刷新的ID令牌,必须使用refresh_token请求openidoffline_access作用域。
在您的客户端注册中,您似乎没有请求offline_access范围,这可能是令牌刷新没有发生的原因。

相关问题