Bienvenidos sean a este post, hoy veremos como autenticarnos en nuestra aplicacione mediante el usuario de twitter o X.
Antes de pasar a nuestras modificaciones en la aplicacion necesitaremos registrar la aplicacion en twitter o X, para ello primero deberan ir a la siguiente URL:
https://developer.twitter.com/en/apps
Aqui les preguntara sobre como cual plan desean para suscribirse, van a tener dos pagos y si miran uno que es gratuito (Free) con todas las limitaciones posibles pero les recomiendo usar para generar dos elementos fundamentales para conectarnos a Twitter como son la key y el secret, en un punto les va a solicitar que saquen una cuenta de desarrollador (developer) para lo cual el dato mas importante que deben completar es un area de texto con una explicacion de porque desean tener la cuenta de desaarrolladdor pero debe ser mayor a 250 caracteres y en ingles, bueno yo lo complete en ingles, y despues aceptar lo de siempre para vender tu alma al diablo o Elon musk en este caso 😅, cuando tengan todo creado, en mi caso fue instantaneo, estaran en el portal de desarrollo, vayan hasta la aplicacion que le registraron y en ella hay una seccion para Key and Tokens, en este caso les recomiendo primero generar en Authentication Tokens las denominadas Access Token and Secret, estas deben guardarlas para usarlas en un futuro, pero no para nuestra aplicacion, una vez hecho quedara la opcion de revoke y regenerate, las que usaremos son las Consumer keys, para las cuales deben usar la opcion regenerate para crear unas nuevas, al igual que en el caso anterior nos dara la opcion de poder copiarlas y almacenarlas para su posterior siendo estas las que realmente usaremos.
Con nuestros elementos de consumer, key y secret, tenemos lo basico para autenticarnos contra Twitter podemos pasar a nuestra aplicacion que trabajamos hasta el post anterior, en caso de no poseerla les dejo un link donde pueden descargarla:
Una vez descargado simplemente extraigan ambos directorios en el PC y ya tenemos nuestra aplicacion lista para ser usada, el directorio users es para nuestro «servidor local» para usuarios, el cual sera parte fundamental de todo esto pero nos centraremos principalmente en nuestra aplicacion y para ello debemos ir al directorio notas donde ejecutaremos el siguiente comaando:
$ npm install dotenv@8.2.x --save
Pero porque debemos instaalar este modulo? bueno, la respuesta es simple, es una recomendacion de Twitter, ya que nos permitira ingresar a las variables en archivos .env donde para este caso almacenaremos los token de conexion con twitter que conseguimos anteriormente, una vez instalado nuestro siguiente paso sera implementarlo y para ello debemos agregar la siguiente linea en app.mjs:
import dotenv from 'dotenv/config.js';
Este basicamente nos permitira poder leer las variables de tipo .env como lo haciamos antes pero ahora tambien podemos leer estos archivos, nuestro sigueinte paso sera crear un archivo con el nombre de .env en el directorio notas y ahi le agregaremos el siguiente codigo:
.env
TWITTER_CONSUMER_KEY = <aca va el valor de tu consumer key>
TWITTER_CONSUMER_SECRET = <aca va el valor de tu consumer secret>
Nuestro siguiente paso sera ir al archivo .gitignore donde verificaremos si se agrego la excepcion a los archivos .env para que no sean sincronizados con el github, si se encuentran no debemos hacer nada de lo contrario agreguenlo al resto, con esto ya tenemos la base para comenzar a trabajar con la estrategia de twitter, si recuerdan en este post cuando vimos como acceder con nuestro usuario local y mencionamos que usamos una estrategia local, ahora haremos algo similar pero con twitter, para ello de nuevo en el directorio notas debemos ejecutar el siguiente comando:
$ npm install passport-twitter@1.x --save
Este se encargara de instalarnos el modulo de passport que nos permitira ingresar a twitter, una vez instalado y en conjunto con el key y secret anteriores podremos trabajar con esto, para ello nuestro siguiente paso sera ira al archivo users.mjs en el directorio routes y agregaremos las siguientes lineas al comienzo:
import passportTwitter from 'passport-twitter';
const EstrategiaTwitter = passportTwitter.Strategy;
La primera sera para importar a nuestro modulo y la segunda para establecer nuestra estrategia, tal como hicimos en este post, sigueindo en el mismo archivo continuaremos agregando las siguientes lineas de codigo:
const twtcallbback = process.env.TWITTER_CALLBACK_HOST
? process.env.TWITTER_CALLBACK_HOST
: "hhttp://localhost:3000";
export var twtLogin;
Lo primero que definiremos sera una variable que contendra el nombre del host que usaremos de callback para cuando la autenticacion a twitter sea exitosa, si la pasamos con una variable la establecera sino pasara la predeterminada, despues declaramos una variable que permitiremos exportarla pero para un poco mas adelante, pasemos a agregar el siguiente bloque de codigo:
if (typeof process.env.TWITTER_CONSUMER_KEY !== 'undefined'
&& process.env.TWITTER_CONSUMER_KEY !==''
&& typeof process.env.TWITTER_CONSUMER_SECRET !=='undefined'
&& process.env.TWITTER_CONSUMER_SECRET !=='') {
passport.use(new EstrategiaTwitter({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL: `${twtcallback}/users/auth/twitter/callback`
},
async function(token, tokenSecret, profile, done) {
try {
done(null, await modeloUsers.buscarCrear({
id: profile.username,
usuario: profile.username,
clave: "",
proveedor: profile.provider,
apellido: profile.displayName,
nombre: "", email: profile.emails,
foto: profile.photos
}));
} catch(err) { done(err); }
}));
twtLogin = true;
} else {
twtLogin = false;
}
Aqui usaremos un condicional para primero verificar que tanto la key como el secret de twitter sean distintos de nada, si es verdadero nuestro primer paso sera crear la nueva estrategia de twitter, tal como hicimos con la local en este post, y al igual que en local definiremos algunas propiedades que son basicamente las claves que obtuvimos al crear nuestro perfil de desarrollador en twitter y la url que actuara como funcion de callback para la API, despues tenemos una funcion asincronica donde recibiremos varios valores, los dos primeros son los tokens devueltos una realizado todo el intercambio entre la API de twitter o X y nuestro modulo passport, el tercer dato sera el perfil que nos devolveran del usuario de Twitter que usamos para ingresar y el ultimo sera el objeto que usaremos para trabajar como siempre para poder utilizarlo le aplicaremos el try/catch para cualquier eventualidad, observen que usamos el done donde primero pasamos un null y luego usamos la funcion buscarCrear de modeloUsers, si no vienen de los posts anteriores esta funcion esta en el servidor de usuarios que creamos en este post y esta se encarga de buscar un usuario y en caso de no encontrarlo procede a crearlo, por esa razon le pasamos todos los campos de nuestra base de datos y como dato le pasamos el proveedor, que en este caso no es local, y los datos son todos los devueltos por twitter.
Despues de enviados esto creara nuestro usuario de manera local pero indicando cual es el proveedor, lo cual nos sera especialmente util para diferenciarlo al momento de usar los ingresos, despues establecemos a la variable twtLogin como true, esto debemos hacerlo por la simple razon de poder habilitar el boton de ingreso mediante twitter, tengan en cuenta que todo lo comentado anteriormente solo se activara al momento de volver la autenticacion mediante twitter y se dirija a nuestra URL de callback, en el caso de no estar logueado ignora todo eso pero nos sirve la verificacion de la key y el secret que establecimos para indicar que tenemos la posibilidad de ingreso, en caso de que no exista la key y el secret procede a establecer como false para que no aparezca en la pagina, con esto comentado continuando en el mismo archivo agreguemos la siguiente linea:
router.get('/auth/twitter', passport.authenticate('twitter'));
Esta sera la primera mencion para comenzar el ingreso con nuestro usuario de twitter, recuerden que la URL completa es /users/auth/twitter/, esta sera enviada mediante el middleware de passport para dar comienzo al proceso de registro con la estrategia de twitter, y aqui da comienzo a la danza de OAuth.
Se lo denomina asi porque una vez iniciado el proceso, el protocola OAuth comienza el redireccionamiento cuidadosos entre varios sitios web, aqui passport se encarga de enviar al navegador en la direccion correcta de twitter, aca nos pregunta si estamos de acuerdo en autenticarnos mediante twitter, para si respondimos afirmativamente redireccionarnos a nuestra direccion de callback, y mientras esto se realiza una gran cantidad de tokens fueron y volvieron entre los distintos sitios web, una vez concluida esta danza el navegador finaliza en la URL que agregaremos a continuacion en users.mjs en routes:
router.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/',
failureRedirect: '/users/login'
}));
Recuerden que la URL completa es /users/auth/twitter/callback y al igual que vimos en este post, despues de procesada la autenticacion tenemos dos posibilidades: el ingreso exitoso que nos redireccionara a la pagina de inicio o el ingreso fallido y nos redirecciona nuevamente a la pagina de ingreso, recuerden que esto es procesado con el bloque de passport.use que comentamos anteriormente, ya que ahora si tiene la direccion URL de callback, con esto ya tenemos todos los temas de ruteo concluido pasemos al siguiente tema que sera en el archivo header.hbs en el directorio partials donde buscaremos este segmento de codigo:
{{else}}
<a class="btn btn-primary" href="/users/login">Ingreso</a>
{{/if}}
Y lo modificaremos de la siguiente manera:
{{else}}
<a class="btn btn-primary" href="/users/login">Ingreso</a>
{{#if twtLogin}}
<a class="btn btn-dark col-auto" href="/users/auth/twitter">
<img width="15px" src="/assets/vendor/twitter/logo-white.png"/>
Log In con X</a>
{{/if}}
{{/if}}
Aqui simplemente le agregamos otro link con forma de boton para poder ingresar mediante twitter, observen que va a la direccion que comentamos anteriormente para poder iniciar todo el proceso de autenticacion mediante OAuth, y a nuestro link le agregamos una imagen proveniente del brand-toolkit de twitter, esta pueden descargarla desde la siguiente direccion:
https://about.twitter.com/en/who-we-are/brand-toolkit
O bien pueden descargar los dos archivos que usaremos para agregar en nuestro proyecto mediante el siguiente link:
Estos dos archivos debemos extraerlos en nuestro proyecto pero antes debemos crear el directorio para ponerlos, primero vayan a public->assets->images, en este ultimo deben crear un nuevo directorio llamado twitter, y aqui extraigan las dos imagenes del archivo anterior, con esto realizado nuestro siguiente paso sera ir al archivo app.mjs y en la seccion donde creamos direcciones mediante express.static le agregaremos el siguiente bloque:
app.use('/assets/vendor/twitter', express.static(
path.join(__dirname, 'public', 'assets', 'images', 'twitter')));
En este caso le decimos que esa URL o path sera para todo el directorio que creamos anteriormente, por lo tanto cuando lo utilicemos en realidad ira donde extrajimos nuestros archivos, igualmente recuerden que al final dejo los codigos modificados durante este post, retomando nuestro trabajo ahora debemos ir al archivo index.mjs en el directorio routes y agregaremos la siguiente linea al inicio:
import { twtLogin } from './users.mjs';
Esto es baasicamente para extraer la variable que se encarga de informarnos que tenemos conectividad con twitter o no, lo siguiente sera buscar el siguiente bloque de codigo en el mismo archivo:
res.render('index', { title: 'Notas',
listanotas: listanotas,
user: req.user ? req.user : undefined
});
Y lo modificaremos de la siguiente manera:
res.render('index', { title: 'Notas',
listanotas: listanotas,
user: req.user ? req.user : undefined,
twtLogin: twtLogin
});
Basicamente es lo mismo pero ahora pasamos como propiedad el logueo en twitter, esto es basicamente para que nos aparezca el boton de login para twitter o X en nuestro archivo de encabezado, nuestro siguiente paso sera ir al archivo notas.mjs en el directorio routes, y al inicio agregaremos esta linea:
import { twtLogin } from './users.mjs';
Lo mismo que en el caso anterior es para importar la variable que nos habilita la posibilidad de estalecer un login con twitter, nuestro siguiente paso sera tomar los siguientes manejadores y debemos agregar la propiedad que indica la posibilidad de poder realizar el logueo en twitter:
router.get('/add', validaAutenticado, (req, res, next) => {
res.render('editarnota', {
title: "Agregar una nota",
creador: true,
clavenota: '',
user: req.user,
twtLogin: twtLogin,
nota: undefined
});
});
router.get('/ver', async(req, res, next) => {
try {
let nota = await notas.read(req.query.clave);
res.render('vistanota', {
title: nota ? nota.titulo : "",
clavenota: req.query.clave,
nota: nota,
twtLogin: twtLogin,
user: req.user ? req.user : undefined
});
} catch(err) { next(err); }
});
router.get('/editar', validaAutenticado, async(req, res, next) => {
try {
const nota = await notas.read(req.query.clave);
res.render('editarnota', {
title: nota ? ("Editando " + nota.titulo) : "Agregar nota",
creador: false,
clavenota: req.query.clave,
nota: nota,
twtLogin: twtLogin,
user: req.user
});
} catch(err) { next(err); }
});
router.get('/borrar', validaAutenticado, async(req, res, next) => {
try {
let nota = await notas.read(req.query.clave);
res.render('borrarnota', {
title: nota ? `Borrar ${nota.titulo}` : "",
clavenota: req.query.clave,
nota: nota,
twtLogin: twtLogin,
user: req.user
});
} catch(err) { next(err); }
});
En todos los casos no modificamos nada sino solamente la posibilidad del tema de logueo con twitter para pasarlo al encargado de renderizar cada una de las paginas para las distintas acciones, las faltantes no es necesario porque son acciones y no paginas para trabajar, con esto ya tenemos todas las modificaciones realizadas solo nos restaria probarlo, no es necesario modificar el inicio en nuestro archivo package.json pero si muchas de las variables que pasamos en nuestros «scripts» de inicio podemos agregarlo en este archivo, si ustedes lo van a probar en el mismo equipo no van a necesitar agregar nada mas pero en mi caso particular como tengo una virtual en la misma lan lo tomo desde ahi por lo tanto no es un localhost y para que funcione agregue la siguiente linea en .env:
TWITTER_CALLBACK_HOST = http://172.128.11.3:3000
Basicamente le indico cual es la direccion de mi servidor para al momento de informar cual sera nuestra direccion de callback, nuestro siguiente paso antes de probarlo sera ir al portal de desarrolladores, ir al proyecto que nos genero automaticamente, en la seccion de Projects & Apps vayan hasta la app y busquen la seccion User Authentication Settings

Aqui deben presionar el boton de Edit y pasaran a la siguiente pagina y deben pasar a la seccion App Info donde lo completaran de la siguiente manera:

Como les comente anteriormente esto es para si se conectan en el mismo equipo donde corren el servidor, pero si lo corren en otro equipo o virtual con una IP distinta deben hacerlo de la siguiente manera:

O bien pueden agregar las dos opciones juntas, en mi caso le pase la IP desde donde lo ejecuto para conectarme, sino hacemos esto al momento de querer conectarse nos devolvera un error de Callback URL, con todo esto ya tenemos nuestra aplicacion lista para ser probada, para ello primero deben correr en una terminal la aplicacion de notas y debe quedar de la siguiente manera:
$ npm start
> notas@0.0.0 start
> cross-env DEBUG=notas:* SEQUELIZE_CONNECT=models/sequelizar-sqlite.yaml MODELO_NOTAS=sequelizar URL_SERVICIO_USER=http://localhost:5858 node ./app.mjs
notas:debug Escuchando en port 3000 +0ms
Con la aplicacion iniciada nuestro siguiente paso sera iniciar el servidor de usuarios, para ello desde otra terminal deben iniciarlo y debe quedar de la siguiente manera:
$ npm start
> user-auth-server@1.0.0 start
> cross-env DEBUG=users:* PORT=5858 SEQUELIZE_CONNECT=sequelizar-sqlite.yaml node ./user-server.mjs
(node:16214) [DEP0111] DeprecationWarning: Access to process.binding('http_parser') is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
users:service user-auth-server escuchando en http://127.0.0.1:5858 +0ms
Por el momento no se preocupen por la notificacion de desechado porque hasta el momento de la publicacion de este post sigue funcionando pero no quita que en un futuro si deje de funcionar, pero con todo esto ya tenemos nuestro entorno recreado solo nos resta probarlo, si abren la aplicacion notas se vera de la siguiente forma

Como pueden ver se habilito el boton para poder ingresar con Twitter o X, el resto sigue funcionando como vimos en posts anteriores, si lo presionamos y no tenemos ninguna sesion abierta del «twitty» nos pasara a la siguiente pantalla

Aqui nos pasara todos los datos de nuestra app creada en el portal de Twitter, con los permisos que hayamos concedido y todas las especificaciones que hayamos pasado, aqui simplemente deben poner el usuario y contraseña de la red social para poder ingresar, si tienen doble autenticacion se las pedira luego, y una vez ingresado aparecera la siguiente pantalla

Esto nos indicara que hemos ingresado correctamente y procede a enviarnos a nuestra aplicacion nuevamente, para que finalmente quede de la siguiente manera

En este caso nos habilito para poder agregar una nueva nota asi como tambien las opciones de borrar o edittar una nota pero con el detalle de que en el boton de salir nos aparece el usuario de twitter, con esto ya tenemos todo terminado pero antes de hacerlo vamos a verificar como quedo nuestra base de datos de usuarios:
$ node ../users/cli.mjs list-users
[
{
id: 'etortore',
usuario: 'etortore',
proveedor: 'local',
apellido: 'Tortore',
nombre: 'Enzo',
email: [],
foto: []
},
{
id: 'mirandma',
usuario: 'mirandma',
proveedor: 'local',
apellido: 'Miranda',
nombre: 'Martin',
email: [],
foto: []
},
{
id: 'tinchicus',
usuario: 'tinchicus',
proveedor: 'twitter',
apellido: 'Martin Miranda',
nombre: '',
email: null,
foto: [ [Object] ]
}
]
$
Si miran los dos primeros usuarios son de tipo local pero el tercero es el que obtuvimos de ingresar mediante Twitter, y por ende el proveedor sera informado de esa manera, el resto de los datos son los que pudimos obtener, por esta razon creamos la funcion de buscar o crear, para los casos de si agregamos mas funcionalidades con los ingresos mediante otras redes sociales o servicios los podamos agregar a la base y mediante el proveedor sepamos como debemos manejarlos, antes de finalizar les dejo un link con todos los archivos del proyecto y codigos modificados en este post:
Nota:
Recuerden que en el archivo .env deben poner sus propias key y secret, el de este archivo estan en blanco.
En resumen, hoy hemos visto como habilitar el ingreso mediante twitter a nuestra aplicacion, para ello hemos habilitado primero nuestro perfil de desarrollador de twitter, de aqui obtuvimos dos claves que son fundamentales para la conexion, asi como hemos visto el paso a paso para establecer la estategia de twitter, la cual hara la «danza» de OAuth, para finalmente tener todo lo necesario y comentar la configuracion final para que funciones, espero les haya sido de utilidad (tal como lo fue para mi) y sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
