【问题标题】:Spring Security: How to revoke a refresh token on log-out?Spring Security:如何在注销时撤销刷新令牌?
【发布时间】:2020-10-19 20:04:59
【问题描述】:

我一直在搜索许多 SO 答案、Git 问题等。我找不到仅使用 Spring Security 而没有弃用的 "Spring Security OAuth" 项目来撤销用户注销时的刷新令牌的方法。

有没有办法自动管理,而不是自己手动向 IdP 发出请求?

我想做的是使用 IdP 撤销端点撤销令牌,在执行注销后遵循 RFC7009 以避免此刷新令牌被脱离上下文和出于安全原因使用。

【问题讨论】:

  • @RuardvanElburg 对不起,也许我解释得不好......我希望 Spring 为我执行 POST 请求,而不是我自己手动进行。

标签: java spring spring-security identityserver4


【解决方案1】:

在打开an issue in GitHub关于Spring Security中当前对RFC7009的支持和自动令牌撤销之后,我已经通过使用一个自定义LogoutHandler实现了一个推荐的解决方案:

我在我的项目中创建了以下类(实现了LogoutHandler):

CustomLogoutHandler.java

package com.test.demo.authorization;

import org.springframework.core.env.Environment;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class CustomLogoutHandler implements LogoutHandler {

    private final Environment env;
    private final OAuth2AuthorizedClientService authorizedClientService;

    public CustomLogoutHandler(Environment env, OAuth2AuthorizedClientService authorizedClientService) {
        this.env = env;
        this.authorizedClientService = authorizedClientService;
    }

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response,
                       Authentication authentication) {
        String clientRegistrationId = ((OAuth2AuthenticationToken) authentication).getAuthorizedClientRegistrationId();
        OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, authentication.getName());
        revokeRefreshToken(authorizedClient.getRefreshToken().getTokenValue());
    }

    private void revokeRefreshToken(String refreshToken) {
        String revocationEndpoint = env.getProperty("spring.security.oauth2.client.registration.test.revocation-endpoint");
        String clientId = env.getProperty("spring.security.oauth2.client.registration.test.client-id");
        String clientSecret = env.getProperty("spring.security.oauth2.client.registration.test.client-secret");

        LinkedMultiValueMap map = new LinkedMultiValueMap();

        map.add("token_type_hint", "refresh_token");
        map.add("token", refreshToken);
        map.add("client_id", clientId);
        map.add("client_secret", clientSecret);

        WebClient revokeTokenWebClient = WebClient.builder()
                .baseUrl(revocationEndpoint).build();

        revokeTokenWebClient
                .post()
                .body(BodyInserters.fromMultipartData(map))
                .retrieve()
                .bodyToMono(String.class)
                .block();

        return;
    }
}

之后,在我的 WebSecurityConfigurerAdapter 的配置方法中,我设置了以下内容:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
      .antMatchers("/img/**", "/favicon.ico", "/logged-out", "/oauth/logout")
      .permitAll()
      .anyRequest()
      .fullyAuthenticated()
      .and()
      .logout()
      .addLogoutHandler(logoutHandler)
      .logoutSuccessHandler(oidcLogoutSuccessHandler());
}

这样做,我已经实现了在退出应用程序时自动撤销refresh_token

【讨论】:

    猜你喜欢
    • 2021-07-05
    • 2017-11-09
    • 2021-09-24
    • 2019-04-12
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 2020-02-20
    • 2021-02-09
    相关资源
    最近更新 更多