Reputation: 21785
I'm building a browser app that requires to authenticate with Google using the OAuth 2.0 / JWT workflow outlined in the link.
In the scenario of success user authentication with Google OAuth 2.0, Google API sends to an app OAuth the response like this:
{
"clientId": "xxx...apps.googleusercontent.com",
"credential": "yyy...123...zzz",
"select_by": "user"
}
I have a client_id and using the NodeJS + JS.
How can I provide the app with the real user data once the user is authenticated?
Upvotes: 10
Views: 17101
Reputation: 662
I was stuck here too, but I found a solution here.
See 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>
I have only adapted the function name, which was provided by @Peheje in the other thread, so that this works with the code example from 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);
}
Upvotes: 3
Reputation: 61
You can use jwt-decode
library to decode your credential OAuth Login, here is the step by step how to use it
jwt-decode
You can use npm install jwt-decode
or yarn add jwt-decode
or pnpm install jwt-decode
jwt-decode
to your App
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);
}
}
}
...
I use GoogleLoginOAuth from @react-oauth/google
, at my case this code it's work!
One more thing, ** just intermezzo ** if you use TypeScript, then you want destructure object to get name
or family_name
for instance
const { given_name, family_name } = USER_CREDENTIAL;
and then you get this error squiggles like this
Property 'family_name' does not exist on type 'unknown'
You can make type like this, copy it if you need it anyway
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
}
and than you can make your code like this
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)
}
}
}
...
Hope it helps!
Upvotes: 6
Reputation: 21785
After some forth and back attempts it got clear that standard import jwt from 'jsonwebtoken'
does not work and Google uses its own encoding npm library - google-auth-library
, see more here. The basic solution is the following:
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 }
}
}
Usage:
const realUserData = getDecodedOAuthJwtGoogle(credential) // credentials === JWT token
If your token (credential) is valid then realUserData
will hopefully have a value like this:
{
// 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"
}
Upvotes: 9