使用Google OAuth验证令牌时遇invalid_grant、授权码格式错误问题
问题根源:令牌类型用错啦!
你碰到的invalid_grant: Malformed auth code错误,核心原因特别简单:客户端传的是Access Token,但服务器端的代码是用来处理Authorization Code的。
你看,客户端里cr.getAccessToken()拿到的是已经通过授权流程兑换好的访问令牌,但服务器端用的GoogleAuthorizationCodeTokenRequest是专门用来把**授权码(Authorization Code)**转换成Access Token的工具——你把Access Token当成授权码塞进去,Google的验证接口自然会判定它格式不对啦!
正确的服务器端验证方案
下面给你两种靠谱的验证Access Token的方法,选哪种都可以:
方法1:直接调用TokenInfo端点验证
这是最直接的方式,向Google的tokeninfo接口发起请求就行:
String clientAccessToken = authToken; // 客户端传来的Access Token HttpTransport transport = new NetHttpTransport(); HttpRequestFactory requestFactory = transport.createRequestFactory(); GenericUrl verifyUrl = new GenericUrl("https://oauth2.googleapis.com/tokeninfo"); verifyUrl.put("access_token", clientAccessToken); HttpRequest request = requestFactory.buildGetRequest(verifyUrl); HttpResponse response = request.execute(); String responseBody = response.parseAsString(); // 解析返回的JSON,你可以拿到token的有效期、关联的客户端ID、权限范围等信息 // 如果token无效,接口会直接返回错误状态码和错误信息
方法2:用GoogleIdTokenVerifier(更规范)
如果想让代码更符合Google OAuth的最佳实践,推荐用GoogleIdTokenVerifier来验证,它会帮你处理很多细节:
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance()) .setAudience(Collections.singletonList(CLIENT_ID)) // 填你的客户端ID .build(); // 验证传入的Access Token TokenInfo tokenInfo = verifier.verifyAccessToken(clientAccessToken); if (tokenInfo != null) { // 验证通过!可以获取token的详细信息 String matchedClientId = tokenInfo.getIssuedTo(); String userId = tokenInfo.getUserId(); Long expiresIn = tokenInfo.getExpiresInSeconds(); // 别忘了再检查一下返回的clientId和你的应用ID是否一致,防止令牌被滥用 if (!matchedClientId.equals(CLIENT_ID)) { throw new RuntimeException("Token belongs to another client!"); } } else { // 令牌无效,直接抛出异常或者返回错误给客户端 throw new RuntimeException("Invalid Access Token"); }
额外提醒
- 一定要保证客户端和服务器端用的
CLIENT_ID、CLIENT_SECRET完全一致,哪怕一个字符错了都不行 - 客户端请求的权限范围(就是你定义的
SCOPES)要和服务器端后续调用API需要的权限匹配,不然就算token验证通过,调用用户信息接口也会报错 - 如果你之后需要获取用户的邮箱、头像这些信息,验证通过后直接用这个Access Token调用
https://www.googleapis.com/oauth2/v2/userinfo接口就行
内容的提问来源于stack exchange,提问作者user2995358
相关产品推荐
相关产品推荐

