Spring Boot中特定重定向URI导致Google OAuth2令牌获取失败求助
解决Spring Boot集成Google SSO换令牌400 Bad Request问题
核心问题分析
你遇到的问题大概率是授权码被重复使用或客户端凭证重复传递导致的:
/login/oauth2/code/google是Spring Security OAuth2 Client的内置回调端点,框架会自动拦截该地址的请求,完成授权码到令牌的交换。等你的自定义代码拿到授权码时,该码已被框架消耗,Google会返回invalid_grant类型的400错误。- 你的代码同时通过Basic Auth头和表单参数传递客户端凭证,Google OAuth2不接受重复的凭证验证方式,也会触发400。
具体解决步骤
1. 避免授权码被框架提前消耗
如果要保留自定义的令牌交换逻辑,有两种方案:
方案A:改用自定义回调端点(已验证可行)
直接修改application.yml中的redirect-uri为你测试正常的地址:
client: registration: google: client-name: Google client-id: XXXXXXX.apps.googleusercontent.com client-secret: XXXXXXXXX redirect-uri: http://localhost:8069/google/oauth2redirect authorization-grant-type: authorization_code scope: - email - profile
该地址不是Spring Security默认端点,框架不会自动处理授权码交换,你的自定义代码可正常使用授权码。
方案B:禁用框架对默认端点的自动处理
若坚持使用/login/oauth2/code/google,需自定义SecurityFilterChain,阻止框架处理该端点的授权码交换:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2Login(oauth2 -> oauth2 .authorizationEndpoint(endpoint -> endpoint.baseUri("/oauth2/authorize")) .redirectionEndpoint(endpoint -> endpoint.baseUri("/custom/oauth2/code/*"))); // 替换为自定义重定向端点前缀 return http.build(); } }
2. 修复客户端凭证重复传递问题
你的代码同时通过Basic Auth头和表单参数传递client_id和client_secret,二选一即可:
选项1:保留Basic Auth头,移除表单参数
修改getUrlParameters方法,去掉client_id和client_secret参数:
public List<NameValuePair> getUrlParameters(String authCode, OAuth2Configuration config) { List<NameValuePair> urlParameters = new ArrayList<>(); if (config.getAuthorizationEndpoint().contains("google")) { urlParameters.add(new BasicNameValuePair("grant_type", "authorization_code")); urlParameters.add(new BasicNameValuePair("code", authCode)); urlParameters.add(new BasicNameValuePair("redirect_uri", config.getAppRedirectUri())); // 移除client_id和client_secret参数 } return urlParameters; }
选项2:移除Basic Auth头,保留表单参数
删除post = httpHelper.addHeader(post, config.getAppClientId(), config.getAppClientSecret());这一行代码,仅保留表单中的凭证参数。
3. 精准定位错误原因
拿到授权码后,用Postman手动请求Google令牌端点,查看具体错误信息:
POST https://oauth2.googleapis.com/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code code=【你的授权码】 client_id=【你的Client ID】 client_secret=【你的Client Secret】 redirect_uri=http://localhost:8069/login/oauth2/code/google
响应体中的error字段会明确错误原因(比如invalid_grant表示授权码无效,invalid_request表示请求参数有误)。
4. 验证redirect_uri完全一致
确保以下三个地方的redirect_uri完全相同:
- Google开发者控制台中配置的授权重定向URI
- 授权请求中的
redirect_uri参数 - 换令牌请求中的
redirect_uri参数
注意大小写、末尾斜杠、HTTP/HTTPS协议等细节,任何不一致都可能导致错误。
内容的提问来源于stack exchange,提问作者Andre Theuma
相关产品推荐
相关产品推荐

