4Geeks logo
Sobre Nosotros

Catálogo de contenidos

Para los geeks autodidactas, este es nuestro extenso catálogo de contenido con todos los materiales y tutoriales que hemos desarrollado hasta el día de hoy.

Tiene sentido comenzar a aprender leyendo y viendo videos sobre los fundamentos y cómo funcionan las cosas.

Data Science and Machine Learning - 16 wks

Full-Stack Software Developer - 16w

Buscar en lecciones

Aprendizaje social y en vivo

La forma más eficiente de aprender: Únete a una cohorte con compañeros, transmisiones en vivo, sesiones improvisadas de codificación, tutorías en vivo con expertos reales y mantenga la motivación.

← Regresar a lecciones
Editar en Github

Comprendiendo JWT y como implementar un JWT simple con Flask

Cómo funciona la autenticación de la API
Implementación de JWT en la API de tu proyecto

Casi todas las API necesitan una capa o layer de autenticación, y hay muchas maneras de abordar ese problema, hoy vamos a implementar el token JWT en nuestra API Flask.

Cómo funciona la autenticación de la API

Puedes dividir un proceso de autenticación estándar en 5 pasos principales:

  1. El usuario escribe su nombre de usuario y contraseña en tu sitio web.
  2. El nombre de usuario y la contraseña se envían a la API de backend.
  3. La API busca cualquier registro en la tabla User que coincida con ambos parámetros al mismo tiempo (nombre de usuario y contraseña).
  4. Si se encuentra un usuario, genera un token para ese usuario y responde status_code=200 al front-end.
  5. El front-end utilizará ese token a partir de ahora para realizar cualquier solicitud futura.

Autentication workflow

☝️ Si no sabes lo que es un token, te recomiendo esta lectura.

¿Qué es JWT?

Hay muchas formas de crear tokens: Basic, Bearer, JWT, etc. Todas ellas son diferentes en su naturaleza, pero el resultado es la misma salida: Un hash (un gran token alfanumérico).

Tipo de tokenEjemplo
Token Básicoecff2099b95ed507a27a4717ec78965d529cc346
Token BearerYWxlc2FuY2hlenI6NzE0YmZhNDNlN2MzMTJiZTk5OWQwYWZlYTg5MTQ4ZTc=
Token JWTeyJhbGciOiJIUzI1NiIsInR5c.eyJzdWIiOFt2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpM

☝️ Como puedes ver, los Tokens JWT son más grandes que los otros dos tipos de token.

JSON Web Token o JWT es un estándar abierto para crear tokens

Este estándar se ha vuelto bastante popular ya que es muy efectivo tanto para las Web Apps como las APIs de Google, donde después de la autenticación del usuario se hacen peticiones a la API.

El Token Web JSON es un tipo de token que incluye una estructura, que puede ser descifrada por el servidor que permite autenticar la identidad del usuario de esa aplicación.

¿Por qué usar JWT Token?

En pocas palabras: JWT es una alternativa increíble porque el Token básicoo Basic Token es demasiado simple y fácil de hackear y el Token Bearer es más difícil de mantener porque tienes que almacenar cada token en la base de datos.

Con los tokens JWT no necesitas una base de datos, el propio token contiene toda la información necesaria.

Autentication workflow

Estructura del token JWT

Autentication workflow

Puedes observar que el string o cadena está dividida en tres secciones separadas por un (.). Cada sección tiene su significado:

Section name
HEADERLa primera parte almacena el tipo de token y el algoritmo de encriptación.
PAYLOADLa segunda parte tiene los datos que identifican al usuario: puede ser su ID, nombre de usuario, etc.
SIGNATUREFirma digital, que se genera con las dos secciones anteriores, y permite verificar si el contenido ha sido modificado.

Implementación de JWT en la API de tu proyecto

Recomendamos encarecidamente el uso de la librería JWT extendida para implementar la autenticación JWT en tu API de Python Flask, el proceso se puede dividir en los siguientes pasos:

1) Incluir la librería JWT en la configuración de tu aplicación Flask

1from flask_jwt_extended import JWTManager 2 3# ya debes tener esta línea en tu proyecto 4# no tienes que añadirla de nuevo 5app = Flask(__name__) 6 7# Configura la extensión Flask-JWT-Extended 8app.config["JWT_SECRET_KEY"] = "super-secret" # ¡Cambia las palabras "super-secret" por otra cosa! 9jwt = JWTManager(app)

2) Crear un endpoint para generar nuevos tokens

El endpoint debe ser un POST porque estás creando tokens (POST es para crear).

1POST /token 2Content-type: application/json 3Body: 4{ 5 "username": "alesanchezr", 6 "password": "12341234" 7}

Así es como podría verse el endpoint en Python:

1from flask_jwt_extended import create_access_token 2# Crea una ruta para autenticar a los usuarios y devolver el token JWT. 3# La función create_access_token() se utiliza para generar el JWT. 4@app.route("/token", methods=["POST"]) 5def create_token(): 6 username = request.json.get("username", None) 7 password = request.json.get("password", None) 8 # Consulta la base de datos por el nombre de usuario y la contraseña 9 user = User.filter.query(username=username, password=password).first() 10 si el User es None: 11 # el usuario no se encontró en la base de datos 12 return jsonify({"msg": "Bad username or password"}), 401 13 14 # crea un nuevo token con el id de usuario dentro 15 access_token = create_access_token(identity=user.id) 16 return jsonify({ "token": access_token, "user_id": user.id }) 17

3) Usar el decorador @jwt_required() en rutas privadas

Ahora... cualquier endpoint que requiera autorización (endpoints privados) debería usar el decorador @jwt_required().

Podrás recuperar la información del usuario autentificada (si es válida) usando la función get_jwt_identity.

1from flask_jwt_extended import jwt_required, get_jwt_identity 2# Protege una ruta con jwt_required, bloquea las peticiones 3# sin un JWT válido presente. 4@app.route("/protected", methods=["GET"]) 5@jwt_required() 6def protected(): 7 # Accede a la identidad del usuario actual con get_jwt_identity 8 current_user_id = get_jwt_identity() 9 user = User.filter.get(current_user_id) 10 11 return jsonify({"id": user.id, "username": user.username }), 200

Implementando JWT en tu proyecto Front-End

En el lado del front-end necesitamos dos pasos principales: Crear un nuevo token (también conocido como "login") y añadir el token a los headers cuando se obtenga cualquier otro endpoint privado.

Crear un nuevo token:

Basándonos en los endpoints que construimos anteriormente tenemos que POST /token con la información del nombre de usuario o username y la contraseña o password en el body de la petición.

1const login = async (username, password) => { 2 const resp = await fetch(`https://your_api.com/token`, { 3 method: "POST", 4 headers: { "Content-Type": "application/json" }, 5 body: JSON.stringify({ username: "joe", password: "1234" }) 6 }) 7 8 if(!resp.ok) throw Error("There was a problem in the login request") 9 10 if(resp.status === 401){ 11 throw("Invalid credentials") 12 } 13 else if(resp.status === 400){ 14 throw ("Invalid email or password format") 15 } 16 const data = await resp.json() 17 // save your token in the localStorage 18 //also you should set your user into the store using the setStore function 19 localStorage.setItem("jwt-token", data.token); 20 21 return data 22}

Obteniendo cualquier información privada

Supongamos que estoy usando la aplicación de front-end y acabo de iniciar sesión, pero ahora quiero obtener algún endpoint privado o protegido:

1// asumiendo que "/protected" es un endpoint privado 2const getMyTasks = await (username, password) => { 3 // retrieve token form localStorage 4 const token = localStorage.getItem('jwt-token'); 5 6 const resp = await fetch(`https://your_api.com/protected`, { 7 method: 'GET', 8 headers: { 9 "Content-Type": "application/json" 10 'Authorization': 'Bearer '+token // ⬅⬅⬅ authorization token 11 } 12 }) 13 if(!resp.ok) throw Error("There was a problem in the login request") 14 15 else if(resp.status === 403){ 16 throw Error("Missing or invalid token"); 17 } 18 else{ 19 throw Error('Uknon error'); 20 } 21 22 const data = await resp.json(); 23 console.log("This is the data you requested", data); 24 return data 25 26}

¡Eso es todo! Como puedes ver es muy sencillo integrar JWT en tu aplicación usando Flask/Python, sólo tres pasos en el backend y dos pasos en el front-ent. Ante cualquier duda puedes contactarme en twitter @alesanchezr o utilizar el canal #public-support en la comunidad Slack de 4Geeks Academy.