Comunidad de diseño web y desarrollo en internet online

Login Social con Node.js

Normalmente en nuestras aplicaciones web llega un momento en el que necesitamos implementar un sistema de registro y autenticación de usuarios.

Podemos programarlo desde cero, pero llega a ser una tarea bastante tediosa, tenemos que tener en cuenta sesiones, privacidad, encriptación de contraseñas, etc,... Si ha esto le sumamos la implementación de un registro con cuenta de Facebook o Twitter como en el acceso a los cursos de Mejorando.la, la cosa se complica bastante.

Para implementar un registro y autenticación de usuarios en Node.js, tenemos la librería Passport. A continuación veremos como implementarlo.



Necesitamos tener Node.js y MongoDB instalados en nuestro entorno. La instalación es diferente según el sistema operativo. Googlea sobre ello, encontrarás información de sobra :)


Configurando nuestro entorno



Seguidamente vamos a crear el esqueleto de una aplicación Node con el framework Express

Código :

$ npm install -g express
$ express login-social
$ cd login-social
$ npm install


A continuación instalamos las dependencias que vamos a emplear en la aplicación, lo hacemos con el flag `--save` para guardarlos en el `package.json`

Código :

$ npm install --save mongoose
$ npm install --save passport
$ npm install --save passport-twitter
$ npm install --save passport-facebook


Vamos a crear un modelo para guardar los datos del usuario. El siguiente código corresponde al archivo models/user.js:


Código :

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var UserSchema = new Schema({
    name: String,
    provider: String,
    provider_id: {type: String, unique: true},
    photo: String,
    createdAt: {type: Date, default: Date.now}
});

var User = mongoose.model('User', UserSchema);


Dando de alta nuestra aplicación en redes sociales



Antes de configuar Passport, vamos a crear una aplicación en Facebook y otra en Twitter para obtener sus claves de API (Key y Secret) y así poder usar esos proveedores en nuestras estrategias de registro.















Estas claves las vamos a indicar en un fichero de configuración ya que es una buena práctica es mantener las API Keys separadas del código fuente que subimos al repositorio, en un archivo `config.js` que luego importamos desde donde lo necesitemos:

Código :

var config = {
  twitter: {
    key: ‘TWITTER_API_KEY’,
    secret: ‘TWITTER_API_SECRET’
  },
  facebook: {
    id: ‘FACEBOOK_APP_ID’,
    secret: ‘FACEBOOK_APP_SECRET’
  }
};

module.exports = config;


Usando passport.js



Lo siguiente que debemos hacer es configurar Passport, para ello hacemos uso de las funciones `serializeUser` y `deserializeUser` hacemos que el objeto que representa al usuario se almacene en la sesión. Las estrategias `TwitterStrategy` y `FacebookStrategy` utilizamos las estrategias de autenticación que nos proporciona Passport. Necesitamos las claves que hemos indicado antes:

passport.js

Código :

var mongoose = require('mongoose');
var User = mongoose.model('User');
var TwitterStrategy = require('passport-twitter').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;
var config = require('./config);

module.exports = function(passport) {

     passport.serializeUser(function(user, done) {
        done(null, user);
    });

     passport.deserializeUser(function(obj, done) {
        done(null, obj);
    });
     passport.use(new TwitterStrategy({
        consumerKey: config.twitter.key,
        consumerSecret: config.twitter.secret,
        callbackURL: '/auth/twitter/callback'
    }, function(accessToken, refreshToken, profile, done) {
        User.findOne({provider_id: profile.id}, function(err, user) {
            if(err) throw(err);
            if(!err && user!= null) return done(null, user);

            var user = new User({
                provider_id: profile.id,
                provider: profile.provider,
                name: profile.displayName,
                photo: profile.photos[0].value
            });
            user.save(function(err) {
                if(err) throw err;
                done(null, user);
            });
        });
    }));
     passport.use(new FacebookStrategy({
        clientID: config.facebook.id,
        clientSecret: config.facebook.secret,
        callbackURL: '/auth/twitter/callback'
    }, function(accessToken, refreshToken, profile, done) {
        User.findOne({provider_id: profile.id}, function(err, user) {
            if(err) throw(err);
            if(!err && user!= null) return done(null, user);

            var user = new User({
                provider_id: profile.id,
                provider: profile.provider,
                name: profile.displayName,
                photo: profile.photos[0].value
            });
            user.save(function(err) {
                if(err) throw err;
                done(null, user);
            });
        });
    }));


Ya podemos configurar el server express con los middlewares `app.js`:

Código :

var mongoose = require('mongoose');
var passport = require('passport');
require('./models/user');
require('./passport')(passport);

mongoose.connect('mongodb://localhost/passport-example', 
  function(err, res) {
    if(err) throw err;
    console.log('Conectado con éxito a la BD');
});
…
app.use(express.cookieParser());
app.use(express.urlencoded());
app.use(express.json());
app.use(express.methodOverride());
app.use(express.session({ secret: 'secretkey' }));

// Configuración de Express
app.use(passport.initialize());
app.use(passport.session());
...
// Rutas de Passport
app.get('/logout', function(req, res) {
  req.logout();
  res.redirect('/');
});
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/twitter/callback', passport.authenticate('twitter',
  { successRedirect: '/', 
    failureRedirect: '/login' }));
app.get('/auth/facebook/callback', passport.authenticate('facebook',
  { successRedirect: '/', 
    failureRedirect: '/login' }));
...


Puedes ver el resto del archivo y los demás de la aplicación en el siguiente repositorio de GitHub: https://github.com/carlosazaustre/passportjs-example

El siguiente controlador, nos renderiza la página `index.html` en la que veremos el enlace al login/registro tanto con facebook como con twitter y en cuando estemos logueados, mostraremos información del usuario:

Código :

exports.index = function(req, res){
  res.render('index', { 
    title: 'Passport-Example',
    user: req.user
  });
};


Esta sería la plantilla HTML, en la que usamos el engine Jade:

Código :

extends layout

block content
  h1= title
  p Welcome to #{title}
  if(user)
    ul
      li
        img(src="#{user.photo}")
      li Bienvenido #{user.name}
      li
        a(href='logout') Salir
  else
    ul
      li
        a(href='auth/twitter') Login con Twitter
      li
        a(href='auth/facebook') Login con Facebook


El flujo de la aplicación sería el siguiente. Primero nos muestra los enlaces para autenticarnos con nuestra cuenta en Twitter o Facebook.



Elegimos Twitter y la apliación nos redirige a la página de Twitter del API para autenticarnos.



Y por último, cuando se finaliza la autenticación, el callback nos devuelve a la URL de inicio donde vemos nuestro nombre, el enlace al `logout` y nuestra foto de twitter.



Tenéis todo el código utilizado disponible y comentado en español en este respositorio de GitHub. Espero que os sirva en vuestros proyectos y desarrollos :)

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate