如何在Spring Boot中从Google OAuth获取Refresh Token?
解决Spring Boot中Google OAuth2获取Refresh Token的问题
核心结论:不能通过request.getParameter("code")获取授权码
Spring Security OAuth2登录流程中,回调请求里的code参数会被框架自动捕获,用来交换Access Token和Refresh Token,这个过程完成后code就会被移除,所以在onAuthenticationSuccess方法里无法通过request参数拿到它。
正确获取Refresh Token的步骤
1. 确保OAuth2请求携带access_type=offline参数
Google OAuth2只有在请求中包含access_type=offline时才会返回Refresh Token,同时添加prompt=consent可以强制用户重新授权,避免用户已授权过就不再返回Refresh Token的情况。
可以通过自定义OAuth2AuthorizationRequestResolver来添加这些参数:
@Bean public OAuth2AuthorizationRequestResolver authorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository) { DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, "/oauth2/authorize"); resolver.setAuthorizationRequestCustomizer(customizer -> customizer .additionalParameters(params -> params.put("access_type", "offline")) .additionalParameters(params -> params.put("prompt", "consent"))); return resolver; }
然后在你的oauth2Login配置中关联这个Resolver:
.oauth2Login() .authorizationEndpoint() .authorizationRequestResolver(authorizationRequestResolver()) .baseUri("/oauth2/authorize") .authorizationRequestRepository(cookieAuthorizationRequestRepository()) .and() // 其他原有配置...
2. 在onAuthenticationSuccess中从Authentication对象提取Refresh Token
框架完成code交换后,会把Access Token和Refresh Token封装到OAuth2AccessToken对象中,你可以从Authentication令牌里直接获取:
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { if (authentication instanceof OAuth2AuthenticationToken oauth2Token) { OAuth2AccessToken accessToken = oauth2Token.getAccessToken(); OAuth2RefreshToken refreshToken = accessToken.getRefreshToken(); if (refreshToken != null) { String refreshTokenValue = refreshToken.getTokenValue(); // 这里可以将refresh token存储到数据库或其他持久化介质 } } // 后续的成功跳转逻辑... }
额外说明
- 你之前构建的
GoogleAuthorizationCodeFlow其实不需要单独使用,Spring Security已经帮你完成了code交换token的流程,直接用框架提供的对象即可。 - 如果是OIDC场景(你配置了
oidcUserService),Refresh Token依然从OAuth2AccessToken中提取,OidcUser的getIdToken()主要存放身份相关信息。
内容的提问来源于stack exchange,提问作者nomadus
相关产品推荐
相关产品推荐

