Google API NodeJS - Getting 401 Unauthorized Error on Subsequent Runs After Successful OAuth2

28 views Asked by At

On first run when token.js file doesn't exist, I get redirected to localhost:3000 with the authenticate() function, and it gets authenticated successfully, afterwards it writes some of credentials to token.js, now on 2nd run, the token.js exist so it will call loadSavedCredentialsIfExist().

Now I get error 401 unauthorized client

Some notes is, I am setting up the Google API on linxu Ubunto and worked perfectly on my windows. I installed gcloud with default login and default Google credentials and still nothing.

It only gets get successfully authentication with redirect oAuth2 screen which I don't always want to do that.

Code below taken from https://developers.google.com/drive/api/quickstart/nodejs with some adjustments:

const path = require('path');
const fs = require('fs').promises;
const process = require('process');
const {
  google
} = require('googleapis');
const {
  authenticate
} = require("@google-cloud/local-auth");
const {
  GoogleAuth
} = require('google-auth-library');

const SCOPES = ['https://mail.google.com/', ' https://www.googleapis.com/auth/calendar']

// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = path.join(__dirname, '/token.json');
const CREDENTIALS_PATH = path.join(__dirname, '/credentials.json');

async function loadSavedCredentialsIfExist() {
  try {
    const content = await fs.readFile(TOKEN_PATH);
    const token = JSON.parse(content);
    // return new GoogleAuth({
    //   client_email: "[email protected]",
    //   private_key: AIzaSyBIUA-YbbZILxVX-w4A_jUVikuOqlq1dDY,
    //   keyFile: CREDENTIALS_PATH,
    //   keyFilename: CREDENTIALS_PATH,

    //   projectId: "whatsapp-gmail-automation",
    //   scopes : SCOPES
    // })
    return google.auth.fromJSON(token);
  } catch (err) {
    return null;
  }
}

/**
 * Serializes credentials to a file compatible with GoogleAUth.fromJSON.
 *
 * @param {OAuth2Client} client
 * @return {Promise<void>}
 */
async function saveCredentials(client) {
  const content = await fs.readFile(CREDENTIALS_PATH);
  const keys = JSON.parse(content);
  const key = keys.installed || keys.web || keys;
  const payload = JSON.stringify({
    type: 'authorized_user',
    client_id: key.client_id,
    client_secret: key.client_secret,
    refresh_token: client.credentials.refresh_token || key.refresh_token,
    access_token: client.credentials.access_token,

  });
  await fs.writeFile(TOKEN_PATH, payload);
}


/**
 * Load or request or authorization to call APIs.
 *
 */
const authorize = async () => {
  let client

  client = await loadSavedCredentialsIfExist();
  if (client) {
    console.log('********************authorize client:', client)

    return client;
  }


  // client = await authenticate({
  //   scopes: SCOPES,
  //   keyfilePath: CREDENTIALS_PATH,
  //   // keyFilename: CREDENTIALS_PATH,
  // });

  // console.log('********************authorize client:', client)
  // if (client.credentials) {
  //   await saveCredentials(client);
  // }

  return client;
}

module.exports = {
  loadSavedCredentialsIfExist,
  saveCredentials,
  authorize,
  CREDENTIALS_PATH,
  TOKEN_PATH
}
0

There are 0 answers