Spring Security Spring 安全5:持久化并访问Oauth2刷新令牌

to94eoyn  于 2022-12-29  发布在  Spring
关注(0)|答案(2)|浏览(258)
    • Spring Boot客户端应用程序如何访问Spring Security 5中Google等提供的刷新令牌?**

非常简单的问题。远程授权服务器(例如Google)发送了一个刷新令牌,我想使用它。在Spring Security 5中持久化和检索它的最佳方法是什么?
似乎this answerthis questionthis exernal link描述的方法在Oauth2成为Spring Security 5中的一等公民后不再兼容。

    • 背景:**

刷新令牌允许客户端应用程序在用户会话过期后继续访问资源。根据Google的文档,刷新令牌应该是持久的:
应用程序应该存储刷新令牌以备将来使用,并使用访问令牌访问GoogleAPI。
springsecurity以OAuth2AuthenticationToken的形式广泛提供了 * 访问令牌 *,但是刷新令牌并不包括在内。
刷新令牌在OidcUserService(或覆盖它的类)中也不可用,因为public OidcUser loadUser(OidcUserRequest userRequest)没有访问刷新令牌的权限。这是一个令人沮丧的问题,因为使用一个自定义类覆盖OidcUserService会很好,该自定义类可以根据用户的OIDC用户详细信息创建/检索用户 *,并同时保存其关联的刷新令牌 *。
OAuth2LoginAuthenticationFilter将刷新令牌保存在ClientRegistrationRepository中:

OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
    authenticationResult.getClientRegistration(),
    oauth2Authentication.getName(),
    authenticationResult.getAccessToken(),
    authenticationResult.getRefreshToken());

this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, oauth2Authentication, request, response);

默认实现将令牌保存在临时内存中,这不适合分布式应用程序,也不适合在重新启动后保持。
似乎有一个JdbcOauth2AuthorizedClientService,带有docs recently added,以及一个表明它可能有用的模式,但没有提供配置它或使用它检索刷新令牌的示例。
那么客户端应用程序如何在SpringSecurity5中持久化并访问刷新令牌呢?

ar5n3qh5

ar5n3qh51#

JdbcOauth2AuthorizedClientService确实适合您的用例,它的配置非常简单,首先,您需要将此表添加到数据库中:

CREATE TABLE oauth2_authorized_client (
  client_registration_id varchar(100) NOT NULL,
  principal_name varchar(200) NOT NULL,
  access_token_type varchar(100) NOT NULL,
  access_token_value blob NOT NULL,
  access_token_issued_at timestamp NOT NULL,
  access_token_expires_at timestamp NOT NULL,
  access_token_scopes varchar(1000) DEFAULT NULL,
  refresh_token_value blob DEFAULT NULL,
  refresh_token_issued_at timestamp DEFAULT NULL,
  created_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
  PRIMARY KEY (client_registration_id, principal_name)
);

然后,配置JdbcOauth2AuthorizedClientService bean:

@Bean
public OAuth2AuthorizedClientService oAuth2AuthorizedClientService
        (JdbcOperations jdbcOperations, ClientRegistrationRepository clientRegistrationRepository) {
    return new JdbcOAuth2AuthorizedClientService(jdbcOperations, clientRegistrationRepository);
}

请注意,当前的实现有一个bug,它将在几天后的spring-security版本5.3.2中得到解决。

cvxl0en2

cvxl0en22#

我尝试使用JdbcOauth2AuthorizedClientService,但遇到以下错误:
[invalid_token_response]尝试检索OAuth 2.0访问令牌响应时出错:500内部服务器错误:"{"时间戳":1672302575797,"状态":500,"错误":"内部服务器错误","异常":"org. glassfish. jersey. server. internal. process.可Map异常","消息":"java. lang.非法参数异常:不支持的内容类型:应用程序/json "",路径":"/oauth2-v1/oauth2/令牌"}"
有趣的是,当我使用InMemoryOAuth2AuthorizedClientService实现时,它工作正常,错误消息看起来与JDBC/DB连接无关。
我也使用postgres模式版本:

CREATE TABLE oauth2_authorized_client (
  client_registration_id varchar(100) NOT NULL,
  principal_name varchar(200) NOT NULL,
  access_token_type varchar(100) NOT NULL,
  access_token_value bytea NOT NULL,
  access_token_issued_at timestamp NOT NULL,
  access_token_expires_at timestamp NOT NULL,
  access_token_scopes varchar(1000) DEFAULT NULL,
  refresh_token_value bytea DEFAULT NULL,
  refresh_token_issued_at timestamp DEFAULT NULL,
  created_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
  PRIMARY KEY (client_registration_id, principal_name)
);

@Stav Shamir你知道这是为什么吗?

相关问题