study sauce | render study sauce cards page | receive an authentication code from google | Search

The code requires several modules, including path, fs, and google-auth-library, and imports custom functions from the ../Core module for interacting with Google Sheets. The authorizeProfile function is the main function, which handles OAuth2 authentication, user data retrieval, and redirects to the home page with the user link.

Run example

npm run import -- "authorize app to read profile info"

authorize app to read profile info

var path = require('path');
var fs = require('fs');
var util = require('util');
var cookie = require('cookie');
var {OAuth2Client} = require('google-auth-library');

var importer = require('../Core');
var getDataSheet = importer.import("get google data sheet");
var updateRow = importer.import("update row in google sheets");
var receiveCode = importer.import("receive an authentication code from google");
var extractProfile = receiveCode.extractProfile;

var SCOPES = [
    'https://www.googleapis.com/auth/userinfo.profile',
    'https://www.googleapis.com/auth/userinfo.email'
];
var credentials = require(process.env.SECRETS_PATH);

function authorizeProfile(req, res) {
    var oauth2Client = new OAuth2Client(
        credentials.installed.client_id,
        credentials.installed.client_secret,
        process.env.AUTH_REDIRECT),
        sessId = (req.cookies || {})['__session'];
    var user;

    return getDataSheet(process.env.DOCID, 'User data')
        .then(users => user = users.filter(u => u.session && u.session === sessId)[0])
        .then(() => {
            var token = JSON.parse((user || {}).token || '""');
            if(token) {
                oauth2Client.setCredentials(token)
                return oauth2Client.getAccessToken();
            }
            throw new Error('invalid_token');
        })
        .then(() => extractProfile(oauth2Client))
        .then(() => res.redirect(process.env.DOMAIN + '/' + user.link + '/home/'))
        .catch(up => {
            if(up.message == 'invalid_token') {
                var authUrl = oauth2Client.generateAuthUrl({
                    access_type: 'offline',
                    scope: SCOPES
                });
                res.redirect(authUrl);
                return authUrl;
            } else {
                throw up;
            }
        })
}

module.exports = authorizeProfile;

What the code could have been:

const path = require('path');
const fs = require('fs');
const cookie = require('cookie');
const { OAuth2Client } = require('google-auth-library');
const logger = require('../utils/logger'); // import logging functionality

const importer = require('../Core');
const {
  getDataSheet,
  updateRow,
  receiveCode,
} = importer.import([
  'get google data sheet',
  'update row in google sheets',
 'receive an authentication code from google',
]);

const SCOPES = [
  'https://www.googleapis.com/auth/userinfo.profile',
  'https://www.googleapis.com/auth/userinfo.email',
];

const secretsPath = process.env.SECRETS_PATH;
const domain = process.env.DOMAIN;
const docId = process.env.DOCID;
const authRedirect = process.env.AUTH_REDIRECT;

/**
 * Authorize user profile
 * 
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 * @returns {Promise} - Redirect URL or authentication error
 */
function authorizeProfile(req, res) {
  try {
    const oauth2Client = new OAuth2Client(
      secretsPath.credentials.installed.client_id,
      secretsPath.credentials.installed.client_secret,
      authRedirect,
    );

    const sessionId = (req.cookies || {}).__session;
    let user;

    // Retrieve user data from Google Sheets
    return getDataSheet(docId, 'User data')
     .then((users) => {
        user = users.find((u) => u.session && u.session === sessionId);
        return user;
      })
     .then((user) => {
        // Check if user has a valid token
        const token = JSON.parse(user && user.token || '""');
        if (token) {
          oauth2Client.setCredentials(token);
          return oauth2Client.getAccessToken();
        }
        throw new Error('invalid_token');
      })
     .then(() => extractProfile(oauth2Client))
     .then(() => res.redirect(`${domain}/${user.link}/home/`))
     .catch((error) => {
        if (error.message === 'invalid_token') {
          // Generate authorization URL
          const authUrl = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: SCOPES,
          });
          res.redirect(authUrl);
          return authUrl;
        }
        logger.error(error);
        throw error;
      });
  } catch (error) {
    logger.error(error);
    throw error;
  }
}

module.exports = authorizeProfile;

Code Breakdown

Requires

The code requires several modules:

Imports

The code imports several custom functions from the ../Core module:

Variables

The code defines several variables:

authorizeProfile Function

The authorizeProfile function is the main function of the code. It takes req and res as arguments and performs the following steps:

  1. Creates an instance of OAuth2Client with the client ID, client secret, and authentication redirect URL.
  2. Retrieves the user data from Google Sheets using getDataSheet.
  3. Checks if the user has an existing token. If yes, sets the OAuth2 client credentials and retrieves the access token.
  4. Extracts the user profile using extractProfile.
  5. Redirects the user to the home page with the user link.
  6. If the token is invalid, redirects the user to the Google authentication page to obtain a new token.

Error Handling

The code catches errors and handles the following cases:

Exports

The code exports the authorizeProfile function.