Skip to content

Instantly share code, notes, and snippets.

@Juandkpa
Last active June 15, 2019 17:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save Juandkpa/222cf75e52fa26d0252b600cf3739135 to your computer and use it in GitHub Desktop.
Save Juandkpa/222cf75e52fa26d0252b600cf3739135 to your computer and use it in GitHub Desktop.
JWT

JWT

Json Web Token, es un estandar abierto (RFC-7519) que define una forma compacta y auto contenida para trasmitir información de manera segura, entre dos partes como un objeto JSON. Esta información puede ser verificada y de confianza por su firma digital. JWTs pueden ser firmados usango un algoritmo secreto como HMAC o algoritmos de llave publica como RSA o ECDSA.

Cuando debería usarse JSON web Tokens?

  • Autorizacíón: Es el escenario más común de utilización de los JWT. Una vez el usuario esta logead, cada solicitud subsecuente debe incluir el JWT, permitiendo al usuario acceder a rutas, servicios y recursos que son permitidos con ese token.
  • Intercambión de información: JSON Web Tokens, son una buena forma de transmitir informacion segura entre partes. Pues pueden ser firmados, por ejemplo, usando una pareja de llave publica y privada se puede estár seguro de que el emisor es quien dice ser. Además como la firma es calculada usando el header y el payload, se puede verificar que el contenido no ha sido modificado.

La explicación de la estructura del json y como se encripta el token podemos encontrarla en jwt.io

JWT en Rails con Knock

Vamos a configurar un sistema de autenticación para nuestra api basado en JWT con ayuda de la gema knock..

Creamos scaffold para gestionar los usuarios del nuestro api

rails g scaffold user name:string email:string:uniq username:uniq password_digest 

nota: los tipos de dato por defecto son strings, por lo tanto en ese caso password_digest lo será

El campo que va a guardar nuestra contraseña, password_digest, es un nombre estándar que vamos a utilizar más adelante para proteger nuestra API.

Configuramos el bcrypt en el modelo user

Esta libreria es la que gestiona la parte de contraseña con el campo password_digest en la tabla users.

Primero se descomenta la gema bcrypt en el archivo Gemfile (se encuentrá ubicado en la raiz de nuestro proyecto)

gem 'bcrypt', '~> 3.1.7'

Ahora es necesario agregar la sentencia has_secure_password al modelo user. (app/models/user.rb)

corremos el gestor de dependencias

$ bundle

Cuando vamos a crear un nuevo usuario en el body de la petición vamos a pasar dos parametros password y password_confirmation, aquí es donde la gema bcrypt hace su trabajo y más específicamente el método has_secure_password. Lo que hace es comparar el password y el password_confirmation y si son iguales, encripta la contraseña en el campo password_digest de la base de datos.

Por razones de seguridad Rails, por defecto evita la asignación masiva de parametros a nuestros modelos, entonces para que podamos hacer una asignación masiva al crear un nuevo usuario, debemos hacer un whitelist (lista de parametros permitidos) en el método user_params (app/controllers/users_controller) de la siguiente manera:

   def user_params
     params.permit(:name, :email,:role_id , :username, :password, :password_confirmation)
   end

Configurar JWT

Configuramos el JWT para la autenticación del api.

  1. En el Gemfile agregamos la gema 'knock´
    $ gem 'knock'
    
  2. Ejecutamos nuevamente el manejador de dependencias
    $ bundle
    
  3. Instalamos y configuramos knock
    $ rails g knock:install
    $ rails g knock:token_controller User
    
  4. En app/controllers/application_controller.rb incluimos la libreria como módulo, agregando al incio de la clase la siguiente linea.
 include Knock::Authenticable 
  1. Luego debemos proteger todos los demás controladores para ello agregamos la linea before_action :authenticate_user en el controlador principal applicationController, como todos los controlladores extienden de el, adquirirán este método y por ende para cualquier petición a alguno de sus métodos el usuario deberá estar autenticado.

  2. Agregamos en el controlador app/controllers/user_token_controller.rb

skip_before_action :verify_authenticity_token, raise: false
  1. En el config/inizializers/knock.rb agregamos
config.token_secret_signature_key = -> { Rails.application.credentials.read }

Y listo, ya podemos probar en postman nuestra autenticación JWT.

Para ello primero creamos un usuario. http://localhost:3000/users con el body:

{
    "name" : "Nuevo Usuario",
    "email": "myemail@email.com",
    "username" : "newUser",
    "password":"123456",
    "password_confirmation": "123456"
}

Luego para solicitar el token de acceso JWT de un determinado usuario, hacemos una peticion a http://localhost:3000/user_token con el body:

{
	"auth":{
		"email": "myemail@email.com",
		"password":"123456"
	}
}

El servicio responderá con el jwt token, que podremos utilizar como autenticación enviandolo para consumir todos los servicios de nuestro api.

{
    "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzg5NTg1NzcsInN1YiI6Mn0.K3PIXtGaGnaOEVdOle_2dg8eB-miSm2OSxOTZE8wgXg"
}

Para poder utilizarlo debemos enviarlo en nuestras peticiones como header utilizando el esquema Bearer así:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzg5NTg1NzcsInN1YiI6Mn0.K3PIXtGaGnaOEVdOle_2dg8eB-miSm2OSxOTZE8wgXg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment