Google One Tap登录后如何通过返回的JWT获取OAuth Access Token
问题说明
查阅Google One Tap登录官方开发文档未找到对应解决方案,当前开发场景需要获取OAuth Access Token,但Google Identity Service的One Tap登录流程不会直接返回OAuth Access Token,仅会返回JWT格式的credential响应,需要实现通过One Tap登录流程获取可用OAuth Access Token的方案。
原有已实现的One Tap登录前端代码如下:
<script src="https://accounts.google.com/gsi/client" async defer></script> <script> window.onload = function () { google.accounts.id.initialize({ client_id: 'myid.apps.googleusercontent.com', callback: handleCredentialResponse }); google.accounts.id.prompt(); } </script> <script> function parseJwt(token) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); }; function handleCredentialResponse(response) { console.log(response); const responsePayload = parseJwt(response.credential); console.log(responsePayload); } </script>
核心结论
One Tap返回的JWT格式credential是OpenID Connect协议的ID Token,仅用于校验用户身份、返回基础用户信息,官方不提供直接用该ID Token兑换OAuth Access Token的接口。要获取Access Token,需要搭配Google Identity Service的OAuth授权模块,在One Tap身份认证流程后无缝触发授权请求,全程无额外跳转,不影响用户体验。
实现步骤
- 提前在Google Cloud控制台对应OAuth客户端的配置页,添加你需要调用的Google API对应的权限范围(scope)。
- 在原有One Tap初始化逻辑的基础上,新增OAuth授权客户端实例。
- 在One Tap的身份认证回调中,静默触发授权请求,复用用户已选择的账号,避免重复弹出选择框。
- 在授权回调中获取需要的OAuth Access Token,用于后续API调用。
改造后可直接运行的代码
<script src="https://accounts.google.com/gsi/client" async defer></script> <script> let oauthTokenClient; window.onload = function () { // 保留原有One Tap身份认证初始化逻辑 google.accounts.id.initialize({ client_id: 'myid.apps.googleusercontent.com', callback: handleCredentialResponse }); google.accounts.id.prompt(); // 新增:初始化OAuth授权客户端 oauthTokenClient = google.accounts.oauth2.initTokenClient({ client_id: 'myid.apps.googleusercontent.com', // 替换为你实际业务需要的API权限范围,多个范围用空格分隔 scope: 'https://www.googleapis.com/auth/userinfo.profile', callback: handleTokenResponse }); } function parseJwt(token) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); }; // One Tap身份认证回调,拿到JWT格式ID Token function handleCredentialResponse(response) { console.log('One Tap返回的JWT凭证:', response.credential); const userBaseInfo = parseJwt(response.credential); console.log('解析得到的用户基础信息:', userBaseInfo); // 身份校验完成后,静默发起授权请求,prompt设为空字符串即可复用已选账号,不重复弹框 oauthTokenClient.requestAccessToken({prompt: ''}); } // OAuth授权回调,拿到Access Token function handleTokenResponse(tokenRes) { if (tokenRes.error) { console.error('授权失败,错误信息:', tokenRes); return; } // 这里就是业务需要的OAuth Access Token const oauthAccessToken = tokenRes.access_token; console.log('获取到的OAuth Access Token:', oauthAccessToken); // 后续调用Google API时,直接将token放在请求头即可,格式为: // Authorization: Bearer <oauthAccessToken> } </script>
注意事项
- 不要尝试通过解析JWT、第三方接口等非官方方式兑换Access Token,这类方案不符合官方安全规范,随时可能失效,还存在用户信息泄露风险。
- 调用
requestAccessToken时必须传入{prompt: ''}参数,否则会重复弹出账号选择窗口,打断One Tap的流畅体验。 - 拿到的Access Token默认有效期为1小时,过期后重新调用
oauthTokenClient.requestAccessToken({prompt: ''})即可静默刷新新的Token,不需要用户手动操作。 - 配置scope时严格遵循最小权限原则,只申请业务实际需要的权限,否则会导致授权通过率下降。
内容的提问来源于stack exchange,提问作者Akash g krishnan
相关产品推荐
相关产品推荐

