Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Cannot read property 'client_secret' of undefined

I'm trying to follow Google's Node API to access gmail here.

When running their sample quickstart as node quickstart.js, I am given the following error:

TypeError: Cannot read property 'client_secret' of undefined
    at authorize (/home/user/example/quickstart.js:32:43)
    at processClientSecrets (/home/example/bstick/quickstart.js:21:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:439:3)
  • I have downloaded the key and renamed it client_secret.json, and copied it to working directory of quickstart.js
  • node --version = 7.8.0, package.json has "google-auth-library": "^0.10.0", "googleapis": "^19.0.0"

Source code(Google's example):

var fs = require('fs');
var readline = require('readline');
var google = require('googleapis');
var googleAuth = require('google-auth-library');

// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-nodejs-quickstart.json
var SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
    process.env.USERPROFILE) + '/.credentials/';
var TOKEN_PATH = TOKEN_DIR + 'gmail-nodejs-quickstart.json';

// Load client secrets from a local file.
fs.readFile('client_secret.json', function processClientSecrets(err, content) {
  if (err) {
    console.log('Error loading client secret file: ' + err);
    return;
  }
  // Authorize a client with the loaded credentials, then call the
  // Gmail API.
  authorize(JSON.parse(content), listLabels);
});

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 *
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, callback) {
  var clientSecret = credentials.installed.client_secret;
  var clientId = credentials.installed.client_id;
  var redirectUrl = credentials.installed.redirect_uris[0];
  var auth = new googleAuth();
  var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

  // Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, function(err, token) {
    if (err) {
      getNewToken(oauth2Client, callback);
    } else {
      oauth2Client.credentials = JSON.parse(token);
      callback(oauth2Client);
    }
  });
}

/**
 * Get and store new token after prompting for user authorization, and then
 * execute the given callback with the authorized OAuth2 client.
 *
 * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
 * @param {getEventsCallback} callback The callback to call with the authorized
 *     client.
 */
function getNewToken(oauth2Client, callback) {
  var authUrl = oauth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES
  });
  console.log('Authorize this app by visiting this url: ', authUrl);
  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  rl.question('Enter the code from that page here: ', function(code) {
    rl.close();
    oauth2Client.getToken(code, function(err, token) {
      if (err) {
        console.log('Error while trying to retrieve access token', err);
        return;
      }
      oauth2Client.credentials = token;
      storeToken(token);
      callback(oauth2Client);
    });
  });
}

/**
 * Store token to disk be used in later program executions.
 *
 * @param {Object} token The token to store to disk.
 */
function storeToken(token) {
  try {
    fs.mkdirSync(TOKEN_DIR);
  } catch (err) {
    if (err.code != 'EEXIST') {
      throw err;
    }
  }
  fs.writeFile(TOKEN_PATH, JSON.stringify(token));
  console.log('Token stored to ' + TOKEN_PATH);
}

/**
 * Lists the labels in the user's account.
 *
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */
function listLabels(auth) {
  var gmail = google.gmail('v1');
  gmail.users.labels.list({
    auth: auth,
    userId: 'me',
  }, function(err, response) {
    if (err) {
      console.log('The API returned an error: ' + err);
      return;
    }
    var labels = response.labels;
    if (labels.length == 0) {
      console.log('No labels found.');
    } else {
      console.log('Labels:');
      for (var i = 0; i < labels.length; i++) {
        var label = labels[i];
        console.log('- %s', label.name);
      }
    }
  });
}
like image 564
cbll Avatar asked Apr 26 '17 16:04

cbll


3 Answers

It seems you must have selected something other than OAuth while generating the credentials.

So as per the steps your config file should look like this

{"installed": //whatever

But if u select Web, then your config file will look like this

{"web":{ //whatever

So open your config file & based on that change this line.

  var clientSecret = credentials.installed.client_secret;
//it should be credentials.whatever-key.client_secret.
//Example : If its web then this line should be credentials.web.client_secret.
like image 94
Parth Ghiya Avatar answered Oct 04 '22 02:10

Parth Ghiya


2020 Update: The "Other" application type no longer exists. But the "Desktop" option provides the same result.

like image 32
Ryan Avatar answered Oct 04 '22 01:10

Ryan


You have either generated the wrong type of credential (see Parth Ghiya's answer) or selected the wrong type of application.

Do the following:

  1. Go to https://console.developers.google.com/apis/credentials
    and click Create credentials button.
  2. Choose OAuth client ID option
  3. Select application type: Other
    (not Web application!)
  4. Give it a name and click Create
  5. Close popup (which shows client ID and client secret)
  6. Click the download icon on your freshly created Credential in the OAuth 2.0 client IDs list
  7. move the downloaded .json file to your project folder
  8. rename the file to client_secret.json
  9. run node quickstart.js

You should be good to go.

like image 35
David Salamon Avatar answered Oct 04 '22 01:10

David Salamon