我正在构建一个浏览器应用程序,需要使用链接中概述的 OAuth 2.0 / JWT 工作流程向 Google 进行身份验证。
在使用 Google OAuth 2.0 成功进行用户身份验证的情况下,Google API 会向应用程序 OAuth 发送如下响应:
{
"clientId": "xxx...apps.googleusercontent.com",
"credential": "yyy...123...zzz",
"select_by": "user"
}
我有一个 client_id 并使用 NodeJS + JS。
用户通过身份验证后,如何向应用程序提供真实的用户数据?
经过一番反复尝试后,我们发现标准的
import jwt from 'jsonwebtoken'
不起作用,Google 使用自己的编码 npm 库 - google-auth-library
,请参阅这里了解更多信息。基本解决方案如下:
const { OAuth2Client } = require('google-auth-library')
/**
* @description Function to decode Google OAuth token
* @param token: string
* @returns ticket object
*/
export const getDecodedOAuthJwtGoogle = async token => {
const CLIENT_ID_GOOGLE = 'yourGoogleClientId'
try {
const client = new OAuth2Client(CLIENT_ID_GOOGLE)
const ticket = await client.verifyIdToken({
idToken: token,
audience: CLIENT_ID_GOOGLE,
})
return ticket
} catch (error) {
return { status: 500, data: error }
}
}
用途:
const realUserData = getDecodedOAuthJwtGoogle(credential) // credentials === JWT token
如果您的令牌(凭证)有效,那么
realUserData
希望具有如下值:
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "[email protected]",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}
您可以使用
jwt-decode
库来解码您的 OAuth 登录凭证,这里是逐步使用它的方法
jwt-decode
您可以使用
npm install jwt-decode
或 yarn add jwt-decode
或 pnpm install jwt-decode
jwt-decode
导入您的应用程序
import { GoogleLogin } from '@react-oauth/google';
import jwtDecode from 'jwt-decode'
...
<GoogleLogin
onSuccess = {credentialResponse => {
if (credentialResponse.credential != null) {
const USER_CREDENTIAL = jwtDecode(credentialResponse.credential);
console.log(USER_CREDENTIAL);
}
}
}
...
我使用来自
@react-oauth/google
的 GoogleLoginOAuth,在我的情况下,这段代码可以工作!
还有一件事,** 只是间奏 ** 如果你使用 TypeScript,那么你想要解构对象以获得
name
或 family_name
例如
const { given_name, family_name } = USER_CREDENTIAL;
然后你会得到这样的错误波形
Property 'family_name' does not exist on type 'unknown'
你可以这样打字,如果你需要的话复制它
dataCredential.ts
export type dataCredential = {
aud: string,
azp: string,
email: string,
email_verified: boolean,
exp: number,
family_name: string,
given_name: string,
iss: string,
jti: string,
name: string,
nbf: number,
picture: string,
sub: string
}
你可以让你的代码像这样
import { GoogleLogin } from '@react-oauth/google';
import jwtDecode from 'jwt-decode'
import {dataCredential} from "../types/dataCredential";
...
<GoogleLogin
onSuccess = {credentialResponse => {
if (credentialResponse.credential != null) {
const USER_CREDENTIAL: dataCredential = jwtDecode(credentialResponse.credential);
console.log(USER_CREDENTIAL);
const { given_name, family_name } = USER_CREDENTIAL;
console.log(given_name, family_name)
}
}
}
...
希望有帮助!
我也被困在这里,但我找到了解决方案这里。
参见谷歌
<div id="g_id_onload"
data-client_id="YOUR_GOOGLE_CLIENT_ID"
data-callback="handleCredentialResponse">
</div>
<script>
function handleCredentialResponse(response) {
// decodeJwtResponse() is a custom function defined by you
// to decode the credential response.
const responsePayload = decodeJwtResponse(response.credential);
console.log("ID: " + responsePayload.sub);
console.log('Full Name: ' + responsePayload.name);
console.log('Given Name: ' + responsePayload.given_name);
console.log('Family Name: ' + responsePayload.family_name);
console.log("Image URL: " + responsePayload.picture);
console.log("Email: " + responsePayload.email);
}
</script>
我只修改了函数名称,该名称是由@Peheje在另一个线程中提供的,以便与来自Google
的代码示例一起使用function decodeJwtResponse(token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
}