You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.3集成Google OAuth2时refresh_token为空问题

解决方案:Spring Boot 3.3 OAuth2 Google登录无法获取Refresh Token

问题根源分析

Google OAuth2仅在首次授权(用户首次同意权限请求)时返回Refresh Token,且必须满足两个核心条件:

  1. 明确指定access_type=offline,告知Google需要离线访问权限
  2. 若用户已授权过相同权限,需强制触发重新授权(添加prompt=consent)才会再次返回Refresh Token

此外,你的配置和代码存在两处关键问题导致无法获取Refresh Token:


步骤1:修正OAuth2客户端配置

不要手动拼接authorization-uri参数,改用Spring Boot官方提供的配置属性来设置离线访问和授权提示,避免配置兼容问题:

修改application.yaml:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: xxxx
            client-secret: xx
            scope: profile, email, openid
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/login/oauth2/code/google
            client-name: Google
            # 开启离线访问,获取Refresh Token的核心配置
            access-type: offline
            # 强制用户重新授权,确保首次/强制授权时返回Refresh Token(开发阶段可用,生产按需调整)
            authorization-request-parameters:
              prompt: consent
        provider:
          google:
            # 恢复官方默认授权地址,由Spring自动拼接参数
            authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
            token-uri: https://oauth2.googleapis.com/token
            user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
            user-name-attribute: sub

配置说明:

  • access-type: offline:明确告知Google需要离线访问权限,这是获取Refresh Token的必要条件
  • prompt: consent:强制用户每次登录都重新确认权限,确保Google返回Refresh Token(生产环境可移除,仅首次授权时触发)

步骤2:修正代码中Principal的获取逻辑

OAuth2AuthorizedClientService.loadAuthorizedClient()需要的是用户的唯一标识(对应OIDC的sub字段,即Authentication的name属性),而非用户的显示名称。同时补充完整的Refresh Token刷新逻辑:

修改OAuth2TokenService的refreshToken方法:

@Service
public class OAuth2TokenService {

    @Autowired
    private OAuth2AuthorizedClientService authorizedClientService;

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    private final RestTemplate restTemplate = new RestTemplate();

    public OAuth2AccessToken refreshToken(Authentication authentication) {
        if (!(authentication instanceof OAuth2AuthenticationToken)) {
            throw new IllegalArgumentException("Invalid authentication type");
        }

        // 直接使用Authentication的name(用户唯一标识,对应OIDC的sub字段)
        String principalName = authentication.getName();
        final String registrationId = "google";
        
        OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient(registrationId, principalName);
        OAuth2RefreshToken refreshToken = authorizedClient.getRefreshToken();

        if (refreshToken == null) {
            throw new IllegalArgumentException("No refresh token found");
        }

        // 执行Refresh Token刷新操作
        ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(registrationId);
        OAuth2RefreshTokenGrantRequest refreshRequest = new OAuth2RefreshTokenGrantRequest(
                clientRegistration,
                authorizedClient.getAccessToken(),
                refreshToken
        );

        OAuth2AccessTokenResponse tokenResponse = new DefaultAuthorizationCodeTokenResponseClient()
                .getTokenResponse(refreshRequest);

        // 更新存储中的授权客户端信息
        authorizedClientService.saveAuthorizedClient(
                new OAuth2AuthorizedClient(
                        clientRegistration,
                        principalName,
                        tokenResponse.getAccessToken(),
                        tokenResponse.getRefreshToken()
                )
        );

        return tokenResponse.getAccessToken();
    }
}

代码修正点:

  1. 简化Authentication类型校验逻辑
  2. 用authentication.getName()获取用户唯一标识,避免手动转换OidcUser可能出现的错误
  3. 补充完整的Refresh Token刷新流程,并更新存储的授权客户端信息

步骤3:测试验证

  1. 清除浏览器中Google的登录状态(或使用隐身窗口),确保触发首次授权流程
  2. 启动应用,访问登录页面完成Google OAuth2授权
  3. 调用refreshToken方法,确认Refresh Token已被正确获取

内容的提问来源于stack exchange,提问作者Alok Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:41:00