如何解码谷歌OAuth 2.0 JWT / 凭据令牌?

6
我正在构建一个浏览器应用程序,需要使用在链接中概述的OAuth 2.0 / JWT工作流程进行与Google的身份验证。在成功使用Google OAuth 2.0对用户进行身份验证的情况下,Google API会向应用程序发送以下响应:
{
  "clientId": "xxx...apps.googleusercontent.com",
  "credential": "yyy...123...zzz",
  "select_by": "user"
}

我有一个client_id并使用NodeJS + JS。

用户认证后,我该如何向应用程序提供真实用户数据?

3个回答

6
经过多次尝试,得出结论:标准的import jwt from 'jsonwebtoken'无法使用,谷歌使用自己的编码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": "testuser@gmail.com",
  "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"
}

很好,但我如何将这个解决方案集成到基于Javascript的Web应用程序中,而该应用程序不使用npm?我需要一个本地的,基于Javascript的解决方案。 - basZero

3

您可以使用 jwt-decode 库来解码您的凭据 OAuth 登录,以下是逐步使用它的步骤

  1. 安装 jwt-decode

您可以使用 npm install jwt-decodeyarn add jwt-decodepnpm install jwt-decode

  1. 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,则希望解构对象以获取例如namefamily_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)
   }
  }
 }
...

希望能够有所帮助!


这真的帮了很多!非常感谢你,阿里! - Student22

0
我也曾陷入困境,但我找到了一个解决方案这里
Google的例子:
看看Google
<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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接