Autenticación con Rails 6.0🔐
Instalando Devise y JWT en un proyecto de Ruby on Rails

$ rails -v
Rails 6.0.0Paso 1 - Crear el nuevo proyecto tipo API 🆕
Para crear nuestro proyecto puedes correr el siguiente comando en la terminal:
$ rails new my_auth_api --apiDespués ingresa al directorio con el comando cd my_auth_api/ y abre el proyecto en tu IDE favorito 💻.
Paso 2 - Agregar la gema devise-jwt💎
Busca el archivo con el nombre de Gemfile en tu proyecto y agrega la siguiente gema:
# Authentication
gem 'devise-jwt'Esta gema además de instalarse, nos ayudará a instalar la gema Devise en nuestro proyecto 🗝.
Si tú lo deseas puedes agregar la gema Devise explicitamente en el Gemfile, ambas opciones funcionarán de la misma forma, pero la siguiente es mejor práctica cuando estás compartiendo tu código con otras personas:
# Authentication
gem 'devise'
gem 'devise-jwt'Una vez agregadas las gemas vamos a correr el siguiente comando en nuestra terminal 🏃♀:
$ bundle installPaso 3: Configurar Devise 👩🍳
Cuando complete la instalación de las gemas podemos proceder a correr el comando para generar los archivos de Devise en nuestro proyecto:
$ rails generate devise:installEste comando generará dos archivos; uno ubicado en config/initializer/devise.rb que contiene la configuración de la gema en nuestro proyecto, y el otro config/locales/devise.en.yml que contiene los mensajes de respuesta de nuestra petición. 📚 En la terminal de igual forma te aparecerá un conjunto de pasos a seguir para terminar de configurar la gema.
De esta lista de pasos, sólo vamos a integrar el número 1, los demás pasos los vamos a omitir, puesto que nuestro proyecto es una API 🥇.
En el archivo config/environments/development.rb agregarás:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }Paso 4: Crear el modelo User 👩🏫
Vamos a crear nuestro modelo llamado User con el siguiente comando en tu terminal:
$ rails generate devise userEste comando nos generará varios archivos nuevos, entre ellos el modelo y la migración, también modificará el archivo de config/routes.rb. 🖍 Para ejecutar la migración y crear la tabla en nuestra base de datos debes correr:
$ rails db:migrateAntes de correr el comando anterior, revisa el archivo de la migración y modificalo según tus necesidades. Para nuestro caso no vamos a cambiar nada 🔒.
Paso 5: Configurar JWT 👩🚀
En el archivo app/models/user.rb vamos a agregar las especificaciones de JWT, en este caso la línea número 2 y 6 de la siguiente imagen:

También agregaremos una columna en nuestra tabla User con el nombre de jti, la cuál configuraremos como índice. Para esto utilizaremos una migración:
$ rails generate migration AddJtiToUserY dentro del archivo que nos cree este comando, escribiremos:

Seguidamente vamos a actualizar las migraciones:
$ rails db:migrateY para terminar, agregaremos la siguiente configuración al final del archivo config/initializers/devise.rb, antes del último end:

Para nuestro caso vamos a tener dos endpoints, /login y /logout, tal como puedes ver en la imagen anterior.
Ahora pon mucha atención en este paso. En la línea número 301 de la imagen anterior, tenemos una variable con el valor Rails.application.credentials.jwt_secret, este valor necesitamos generarlo en nuestra terminal con el siguiente comando:
$ rails secretLo cuál nos retornará una llave de acceso parecida a esta:
dcbc939cbd1efa3a19f73fb2eda9ecdcd12a6daaaaad64e0dcc24e1550379615835db39e6950f71e32a0ea4a30a93a5cfacded8e562d3503889790daa094cd37La llave anterior debe ser almacenada muy cuidadosamente. Para esta misión usaremos el archivo que está en nuestro proyecto llamado credentials.yml.enc, el cuál es un archivo encriptado que Rails nos facilita para poder manejar datos sensibles 🚫. Para accederlo, en la terminal podemos correr el siguiente comando:
$ EDITOR=nano bin/rails credentials:edit Ahí agregaremos el valor que nos arrojó la terminal de la siguiente forma:

Dentro del archivo encontrarás que ya existe una variable llamada secret_key_base, debajo de ella crearemos una nueva con el nombre jwt_secret y al lado pegaremos el valor obtenido de la terminal anteriormente.
OJO: Nota que ni las variables ni el valor guardado lleva comillas y que la asignación del valor se hace con dos puntos (:) y no van separados por comas (;), por otro lado, todo lo que tenga # son interpretados como comentarios, es decir, son valores ignorados.
En la parte inferior de la terminal, se indican los comandos para salir del editor: ctrl + X, luego me preguntará si deseo guardar los cambios para lo que presionamos Y(en caso de no querer cambiarlos presionamos N) y finalmente enter.
Paso 6: Crear endpoints ↪↩
Ahora generaremos las rutas que necesitamos para poder crear un usuario y obtener un token al iniciar sesión. Para eso vamos a editar el archivo config/routes.rb de la siguiente forma:

En donde usaremos el endpoint /signup para crear un nuevo usuario, /login para obtener el token de inicio de sesión y /logout para destruir el token y la sesión existente.
Paso 7: Controladores ⚙
Si no se necesitan cosas extra además de las que Devise trae por defecto en sus controladores, lo mejor es no modificarlos. Sin embargo es necesario indicarle a Devise que queremos que retorne sus respuestas en formato JSON, tanto al manejador de registro como el de sesión.
Para eso modificaremos el archivo app/controllers/sessions_controller.rb, si no existe puedes crearlo y agregar:

Y también el archivo app/controllers/registrations_controller.rb, si no existe puedes crearlo y agregar:

Con esto ya podemos inicializar el servidor de Rails usando:
$ rails serverY probar nuestros endpoints en Postman, primero creando un usuario:

En la petición anterior esperamos recibir un Status: 201, y toda la información de la base de datos para ese usuario en particular, es decir: id, email, created_at, updated_at y jti.
Y después generando un token de autenticación para ese usuario:


Con esto ya tienes un API de autenticación que puedes utilizar en cualquier proyecto que necesite un manejador de usuarios.
Puedes encontrar el repo de este proyecto aquí: https://github.com/nahrivera7/authentication-api
