Passport es un módulo de autenticación simple para Node.js.

Crea un proyecto en Heroku, en mi caso el proyecto se llama passportjs-google-example, así que reemplaza el nombre del proyecto por el que tú necesites.

Agrega tu proyecto ejecutando el comando siguiente:

$ heroku login
$ git init
$ heroku git:remote -a passportjs-google-example

Recuerda reemplazar passportjs-google-example por el nombre de tu proyecto en heroku.

Crea un proyecto para obtener id y llave secreta de autenticación (oAuth 2.0) de google.

https://console.developers.google.com/

Los datos que utilizaremos serán:

  • ID DE CLIENTE
  • SECRETO DE CLIENTE

Crea un archivo package.json que contiene las dependencias:

{
  "name": "passportjs-google-example",
  "version": "0.0.0",
  "dependencies": {
    "body-parser": "^1.9.3",
    "cookie-parser": "^1.3.3",
    "express": "^4.10.4",
    "express-session": "^1.9.3",
    "morgan": "^1.5.0",
    "passport": "^0.2.1",
    "passport-google-oauth": "^0.1.5"
  },
  "engines": {
    "node": "0.10.x"
  }
}

Instala las dependencias ejecutando el comando siguiente:

$ npm install

Crea un archivo llamado config.js con el contenido siguiente:

var config = {
  google: {
    client: {
      id: process.env.GOOGLE_CLIENT_ID || '',
      secret: process.env.GOOGLE_CLIENT_SECRET || '',
      callbackUrl: process.env.GOOGLE_CALLBACK_URL || ''
    }
  },
  session: {
    secret: process.env.SESSION_SECRET || ''
  }
}

module.exports = config;

Deberás establecer una variable de entorno llamada GOOGLE_CLIENT_ID con el contenido de ID DE CLIENTE , otra llamada GOOGLE_CLIENT_SECRET con el contenido de SECRETO DE CLIENTE, GOOGLE_CALLBACK_URL con el url de tu dominio pero agregando /auth/google/callback, SESSION_SECRET con un texto único para asegurar la sesión o dentro de '' poner el contenido respectivamente.

Ejemplo:

...
client: {
    id: '18373652947-7ld5dnflhicpjandqjle485ckbck943q.apps.googleusercontent.com',
    secret: 'PLtXBkOpHTnllRDyvVd9PLZI ',
    callbackUrl: 'http://passportjs-google-example.herokuapp.com/auth/google/callback'
},
session: {
    secret: 'jnkajsndi12nqnkqwejqwe'
}
...

Ahora creamos un archivo llamado app.js con el contenido siguiente:

var express = require('express');
var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var cookieParser = require('cookie-parser');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var session = require('express-session');
var config = require('./config');

// Passport session setup.
//   To support persistent login sessions, Passport needs to be able to
//   serialize users into and deserialize users out of the session.  Typically,
//   this will be as simple as storing the user ID when serializing, and finding
//   the user by ID when deserializing.  However, since this example does not
//   have a database of user records, the complete Google profile is
//   serialized and deserialized.
passport.serializeUser(function(user, done) {
  done(null, user);
});

passport.deserializeUser(function(obj, done) {
  done(null, obj);
});

// Use the GoogleStrategy within Passport.
//   Strategies in Passport require a `verify` function, which accept
//   credentials (in this case, an accessToken, refreshToken, and Google
//   profile), and invoke a callback with a user object.
passport.use(new GoogleStrategy({
  clientID: config.google.client.id,
  clientSecret: config.google.client.secret,
  callbackURL: config.google.client.callbackUrl
},
function(accessToken, refreshToken, profile, done) {
  // asynchronous verification, for effect...
  process.nextTick(function() {
    console.log(profile);

    // To keep the example simple, the user's Google profile is returned to
    // represent the logged-in user.  In a typical application, you would want
    // to associate the Google account with a user record in your database,
    // and return that user instead.
    return done(null, profile);
  });
}
));

var app = express();

// configure Express
app.use(morgan(':method :url :response-time'));
app.use(cookieParser());
app.set('json spaces', 2);
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: false
}));
// parse application/json
app.use(bodyParser.json());
app.use(session({
  secret: config.session.secret,
  resave: false,
  saveUninitialized: true
}));

// Initialize Passport!  Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());

app.get('/', function(req, res) {
  if (!req.user) {
    res.redirect('/auth/google');
  }
  else {
    res.json(req.user);
  }
});

// GET /auth/google
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  The first step in Google authentication will involve
//   redirecting the user to google.com.  After authorization, Google
//   will redirect the user back to this application at /auth/google/callback
app.get('/auth/google',
passport.authenticate('google', {
  scope: [
  'https://www.googleapis.com/auth/userinfo.profile',
  'https://www.googleapis.com/auth/userinfo.email'
  ]
}),
function(req, res) {
  // The request will be redirected to Google for authentication, so this
  // function will not be called.
});

// GET /auth/google/callback
//   Use passport.authenticate() as route middleware to authenticate the
//   request.  If authentication fails, the user will be redirected back to the
//   login page.  Otherwise, the primary route function function will be called,
//   which, in this example, will redirect the user to the home page.
app.get('/auth/google/callback',
passport.authenticate('google', {
  failureRedirect: '/login'
}),
function(req, res) {
  res.redirect('/');
});

app.get('/logout', function(req, res) {
  req.logout();
  res.redirect('/');
});

app.listen(process.env.PORT || 3000);

// Simple route middleware to ensure user is authenticated.
//   Use this route middleware on any resource that needs to be protected.  If
//   the request is authenticated (typically via a persistent login session),
//   the request will proceed.  Otherwise, the user will be redirected to the
//   login page.
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login');
}

Crea un archivo llamado Procfile con el contenido siguiente:

web: node app.js

Ahora agrega los archivos al repositorio y haz el despliegue a heroku:

$ git add .
$ git commit -m "Init"
$ git push heroku master

Abre el sitio con el comando siguiente:

$ heroku open

Debería mandarte a la pestaña en el explorador de internert (Chrome, Firefox, IE, etc) en donde te autenticas y concedes los permisos de tu cuenta de google, luego debería redireccionarte a la página en heroku donde verás los datos de tu cuenta, en mi caso fue este:

{
  "provider": "google",
  "id": "100373413058806300402",
  "displayName": "Paulo Antonio McNally Zambrana",
  "name": {
    "familyName": "McNally Zambrana",
    "givenName": "Paulo Antonio"
  },
  "emails": [
    {
      "value": "paulomcnally@gmail.com"
    }
  ],
  "_raw": "{\n \"id\": \"100373413058806300402\",\n \"email\": \"paulomcnally@gmail.com\",\n \"verified_email\": true,\n \"name\": \"Paulo Antonio McNally Zambrana\",\n \"given_name\": \"Paulo Antonio\",\n \"family_name\": \"McNally Zambrana\",\n \"link\": \"https://plus.google.com/+PauloAntonioMcNallyZambrana\",\n \"picture\": \"https://lh3.googleusercontent.com/-juVPYjy4afI/AAAAAAAAAAI/AAAAAAAABlY/01mwq0MJ8jQ/photo.jpg\",\n \"gender\": \"male\",\n \"locale\": \"en\"\n}\n",
  "_json": {
    "id": "100373413058806300402",
    "email": "paulomcnally@gmail.com",
    "verified_email": true,
    "name": "Paulo Antonio McNally Zambrana",
    "given_name": "Paulo Antonio",
    "family_name": "McNally Zambrana",
    "link": "https://plus.google.com/+PauloAntonioMcNallyZambrana",
    "picture": "https://lh3.googleusercontent.com/-juVPYjy4afI/AAAAAAAAAAI/AAAAAAAABlY/01mwq0MJ8jQ/photo.jpg",
    "gender": "male",
    "locale": "en"
  }
}

Demo

https://passportjs-google-example.herokuapp.com/

Repositorio

https://github.com/paulomcnally/passportjs-google-example.git