Registro y autorización de usuarios en Node.js con Twitter y Facebook

22 de marzo de 20146 min lectura·nodejsjavascripttutorial
Aprende a implementar registro y autorización de usuarios en Node.js usando OAuth con Twitter y Facebook paso a paso con ejemplos prácticos en vídeo

El pasado viernes me ofrecieron impartir una clase BONUS en la plataforma de estudiantes de los cursos de Mejorando.la.

El tema que elegimos fue como implementar un sistema de login de usuarios utilizando plataformas sociales (Twitter y Facebook) y empleando Node.js en el Backend.

Y a continuación explico a modo de tutorial los pasos para implementar este sistema en un proyecto que tengamos.

Requisitos previos

Lo primero de todo, necesitamos tener Node.js y MongoDB instalados en nuestro equipo. Node es el backend que utlizaremos y MongoDB es una base de datos no relacional, basada en documentos JSON. Podemos utlizar cualquier otra base de datos (por ejemplo, MySQL o cualquier otra). Yo lo hago con Mongo porque me parece más sencillo y porque esta basada en JavaScript del cual soy un talifán :P

Estructura base del proyecto con Express

A continuación creamos una estructura base de aplicación con el framework Express. De esta forma nos crea un “esqueleto” con archivos y carpetas de una especie de “hola mundo” con Express.

shell
$ sudo npm install -g express
$ express passport-example
$ cd passport-example
$ npm install

Instalamos las dependencias que vamos a utilizar. Mongoose es el driver que nos ayuda a conectarnos a MongoDB e implementar esquemas de los modelos que salvemos en la base de datos. Passport es la librería que nos permite agilizar el proceso de autenticado y registro de usuarios con Node.js. Passport-twitter y Passport-facebook son las librerías específicas para el login con Twitter y Facebook ya que podemos utilizar Passport sin redes sociales implementando un método local con Passport-Local.

Con el prefijo –-save logramos que las dependencias se queden grabadas en el package.json

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

Modelo de usuario con Mongoose

Creamos un modelo usuario /models/user.js donde indicaremos que datos vamos a querer almacenar en la base de datos para nuestros usuarios. En este ejemplo vamos a salvar el nombre, el proveedor, un ID, la foto del usuario y un campo dónde almacenaremos la fecha en la que el usuario se registró en nuestra aplicación.

JavaScript
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);

Configuración de Passport y estrategias OAuth

Configuramos Passport /passport.js* importando las librerías que utilizamos y las funciones que nos permiten el login.

Con seriealizeUser y deserializeUser logramos que el objeto usuario quede almacenado en la sesión de la aplicación y asi poder utilizarlo a lo largo de ella.

Con TwitterStrategy y FacebookStrategy utilizamos las estrategias de autenticación que nos proporciona Passport, les pasamos como parámetros los API Key y API secret que nos dan las plataformas cuando registramos una aplicación en ellas, y nos devuelven varios objetos, entre ellos el objeto profile que contiene toda la información del usuario que devuelve Twitter o Facebook y del que podemos sacar los atributos que queramos para nuestra aplicación (nombre, ID, foto, etc..)

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

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: 'TWITTER_CONSUMER_KEY',
		consumerSecret: 'TWITTER_CONSUMER_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: 'FACEBOOK_APP_CLIENT_ID',
		clientSecret: 'FACEBOOK_APP_SECRET_ID',
		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);
			});
		});
	}));

Gestión de API Keys y configuración

Una buena práctica es mantener las API Keys separadas del código fuente que subimos al repositorio, en un archivo config.js (o en las variables de entorno) que luego importamos desde donde lo necesitemos.

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

module.exports = config;

El archivo principal de la aplicación Express y por tanto del servidor quedaría mas o menos así app.js

javascript
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' }));
...

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

Esta sería la plantilla Jade que renderiza el index: /views/index.jade. Como véis le aplicamos una lógica dentro de la plantilla. Si existe el objeto usuario es que estamos logueados en la aplicación y por tanto le pedimos que nos muestre la foto y el nombre y un enlace a salir. En caso de que no exista el objeto usuario es que no estamos logueados, por tanto indicamos que nos muestre los enlaces al registro/login con Twitter y Facebook

pug
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

Para crear una aplicación en Twitter podemos ir a http://dev.twitter.com y registrar una nueva aplicación. Indicamos el nombre y en los campos website y callback URL le ponemos example.com ya que no nos permite poner Localhost. Con facebook es similar, la URL es http://developers.facebook.com y en este caso si podemos indicarle que nuestra aplicación funciona en localhost.

Aquí están las capturas para ambas plataformas:

Screen Shot 2014-03-02 at 22.42.12.png

Screen Shot 2014-03-02 at 22.44.15.png

Screen Shot 2014-03-02 at 22.43.12.png

Screen Shot 2014-03-03 at 10.29.37.png

Screen Shot 2014-03-02 at 22.46.37.png

Screen Shot 2014-03-03 at 09.10.27.png

Y ya está, el flujo de la aplicación sería el siguiente: Primero nos pide autenticarnos con Twitter o Facebook

Screen Shot 2014-03-03 at 10.45.01.png

Si elegimos Twitter nos redirige a la página de autenticación con Twitter. En el caso de no estar logueados nos pediría el usuario y la contraseña de Twitter

Screen Shot 2014-03-03 at 10.45.05.png

Y si todo sale correctamente, nos redirige a nuestra aplicación con el usuario logueado, mostrándonos el nombre de usuario y la foto de perfil

Screen Shot 2014-03-03 at 10.45.09.png

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 :)

← Todos los artículos
Compartir en XCompartir en LinkedIn
También te puede interesar

Artículos relacionados

nodejsjavascript

Cómo crear un API REST usando Node.js, Express y MongoDB

sept 201713 min
nodejsjavascript

WebSockets: Cómo utilizar Socket.io en tus aplicaciones web

sept 20158 min
nodejsjavascript

Cómo implementar autenticación basada en token con Node.js

feb 20156 min
Newsletter · AprendiendoDEV

Aprende más cada semana.

Noticias de JavaScript, arquitectura de software e IA, directas a tu bandeja de entrada. Sin spam, puedes darte de baja cuando quieras.

Powered by Substack · Sin spam · Baja cuando quieras