Google Integrated Auth JWT Validation Failure

48 views Asked by At

Any idea where I am going wrong in verifying the JWT I get back from integrated Google Auth? My React web app receives the token, which I pass to my Node.js backend, where I attempt to verify the token. I have decoded the token and all the info I would expect to be in the payload is there. But when I attempt to verify the token, I get the error, "Invalid token signature". As you can see in the code below, I have tried using Google's package, 'google-auth-library', and as an alternate approach I manually downloaded the Google public key and using the package 'jsonwebtoken'. Both report the token as invalid. I'm pretty sure the token / signature is not invalid, so there must be something I'm doing wrong. I double checked, and the Google client ID I use in my React app matches what I'm using in my Node.js backend.

One other bit of background, I've setup a project in Google Cloud, and in the Credentials section, have configured an "OAuth 2.0 Client ID" which is where my google client Id referenced in the code comes from, and as far as I can tell, I have followed the instructions provided by Google here

import * as jwt from 'jsonwebtoken'
import { OAuth2Client } from 'google-auth-library'
import { getConfig } from '../tools/config'

export const verifyGoogleJwt = async (token: string) => {
  // Try to use 'google-auth-library' to verify
  try {
    const config = await getConfig()
    const client = new OAuth2Client(config.googleClientId)
    const ticket = await client.verifyIdToken({
      idToken: token,
      audience: config.googleClientId,
    })
    return ticket.getPayload()
  } catch (error) {
    console.error('OAuth2Client.verifyIdToken failed:', error.message)
  }

  // Try to use 'jsonwebtoken' to manually verify with Public Key
  try {
    // From https://www.googleapis.com/oauth2/v1/certs
    const googlePublicKey =
      '-----BEGIN CERTIFICATE-----\nMIIDJzCCAg+gAwIBAgIJAO5q5hCX9S+zMA0GCSqGSIb3DQEBBQUAMDYxNDAyBgNV\nBAMMK2ZlZGVyYXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20w\nHhcNMjMxMTA0MDQzODA0WhcNMjMxMTIwMTY1MzA0WjA2MTQwMgYDVQQDDCtmZWRl\ncmF0ZWQtc2lnbm9uLnN5c3RlbS5nc2VydmljZWFjY291bnQuY29tMIIBIjANBgkq\nhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuB+3s136B/Vcme1zGQEg+Avs31/voau8\nBPKtvbYhB0QOHTtrXCF/wxIH5vWjl+5ts8up8Iy2kVnaItsecGohBAy/0kRgq8oi\n+n/cZ0i5bspAX5VW0peh/QU3KTlKSBaz3ZD9xMCDWuJFFniHuxLtJ4QtL4v2oDD3\npBPNRPyIcZ/LKhH3+Jm+EAvubI5+6lB01zkP5x8f2mp2upqAmyex0jKFka2e0DOB\navmGsGvKHKtTnE9oSOTDlhINgQPohoSmir89NRbEqqzeZVb55LWRl/hkiDDOZmcM\n/oJ8iUbm6vQu3YwCy+ef9wGYEij5GOWLmpYsws5vLVtTE2U+0C/ItQIDAQABozgw\nNjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggr\nBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOCAQEAifQankV6Ca4UQ9MvTX4KlsaVV6WR\n1FL2ZwRPHwFQnw3hFJrHKdQBvCS1339G1uguCOi0CQQJmQauSvRureJ/80Fc/j3c\nwEWQgBhuKCHiQbIMFpVoljsVsF91E0FvZ8eJJ5/y7QB3Ww68FavXNjZ62GaYp8aw\nEdqJdqNFaIv7yWzOO27filjzF3H6VJG7ucx0P6JCCCC6HSii3o1lkRISvSTcevqZ\nsFdbJEqtVU70siOHxWxMqRopetiTEAsbvwiicdZ6flZqtnxKqB6YEb6TocWpzGvd\nVKxzByXdPJbyYvAnvusborJZPHKbleZjyonK+cmsOU6N1Yn/FUxKKhFXEg==\n-----END CERTIFICATE-----\n'
    return jwt.verify(token, googlePublicKey)
  } catch (error) {
    console.error('jsonwebtoken.verify failed:', error.message)
  }
}
0

There are 0 answers