Tutorial para Crear una API RESTful Segura con Python, Flask y Autenticación JWT
Introducción
En este tutorial aprenderás a crear una API RESTful segura usando Python, Flask y JSON Web Tokens (JWT) para la autenticación y autorización. Está diseñado para desarrolladores principiantes e intermedios que quieran iniciarse en el desarrollo backend seguro con Python. A lo largo del tutorial, veremos desde la configuración del entorno, la creación de rutas CRUD básicas hasta la implementación completa de autenticación JWT y el manejo de errores. Además, aprenderás a probar tu API con Postman.
Este tutorial te ayudará a dominar conceptos clave como:
- Configuración y uso de Flask para desarrollo backend
- Crear rutas RESTful para operaciones CRUD
- Implementar autenticación y autorización con JWT en Flask
- Manejo adecuado de errores y respuestas de la API
- Probar endpoints con Postman
¡Comencemos!
1. Preparación del Entorno de Desarrollo
1.1 Instalación de Python
Primero asegúrate de tener instalado Python 3.6 o superior.
Para verificar, ejecuta en tu terminal:
1 2 |
python --version |
Si no lo tienes, descárgalo desde python.org.
1.2 Crear y activar un entorno virtual
Para manejar dependencias, es buena práctica usar un entorno virtual:
1 2 3 4 5 6 7 8 |
# En Linux/macOS python -m venv venv source venv/bin/activate # En Windows python -m venv venv venv\Scripts\activate |
1.3 Instalación de dependencias
Instalaremos Flask y extensiones necesarias:
1 2 |
pip install Flask PyJWT Flask-RESTful |
- Flask: microframework para web
- PyJWT: para generar y verificar JWT
- Flask-RESTful: para facilitar la creación de APIs RESTful
2. Creación del Proyecto Flask con Rutas CRUD
Vamos a crear una API simple para manejar un recurso llamado “items”.
2.1 Estructura inicial
Crea un archivo app.py
y agrega:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from flask import Flask, request, jsonify from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) items = [] # lista simple para almacenar los ítems (simula base de datos) class Item(Resource): def get(self, name): item = next((item for item in items if item['name'] == name), None) if item: return item, 200 return {'message': 'Item not found'}, 404 def post(self, name): if next((item for item in items if item['name'] == name), None): return {'message': f"An item with name '{name}' already exists."}, 400 data = request.get_json() item = {'name': name, 'price': data.get('price', 0)} items.append(item) return item, 201 def delete(self, name): global items items = [item for item in items if item['name'] != name] return {'message': 'Item deleted'}, 200 def put(self, name): data = request.get_json() item = next((item for item in items if item['name'] == name), None) if item: item.update(data) return item, 200 item = {'name': name, 'price': data.get('price', 0)} items.append(item) return item, 201 class ItemList(Resource): def get(self): return {'items': items}, 200 api.add_resource(Item, '/item/<string:name>') api.add_resource(ItemList, '/items') if __name__ == '__main__': app.run(debug=True) |
2.2 Explicación
- Usamos
flask_restful.Resource
para definir recursos. items
es una lista que simula una base de datos.- Las rutas CRUD cubren:
GET /item/<name>
: obtener un ítemPOST /item/<name>
: crear un ítemDELETE /item/<name>
: borrar un ítemPUT /item/<name>
: crear o actualizar un ítemGET /items
: listar todos
2.3 Prueba rápida
Inicia el servidor:
1 2 |
python app.py |
Por ejemplo, para crear un nuevo ítem con curl:
1 2 |
curl -X POST -H "Content-Type: application/json" -d '{"price": 25}' http://localhost:5000/item/book |
Luego:
1 2 |
curl http://localhost:5000/item/book |
3. Implementación de Autenticación y Autorización con JWT
3.1 ¿Qué es JWT?
JSON Web Tokens (JWT) permiten comunicar información segura mediante tokens firmados. Son ideales para autenticación stateless en APIs.
3.2 Instalación adicional
Instalaremos Flask-JWT para facilitar la integración:
1 2 |
pip install Flask-JWT |
3.3 Configuración básica de JWT
Actualiza app.py
para añadir autenticación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
from flask_jwt import JWT, jwt_required, current_identity from werkzeug.security import safe_str_cmp # Simulación de usuario almacenado def authenticate(username, password): if username == 'admin' and password == 'password': return {'id': 1, 'username': 'admin'} def identity(payload): user_id = payload['identity'] if user_id == 1: return {'id': 1, 'username': 'admin'} app.config['SECRET_KEY'] = 'super-secret-key' jwt = JWT(app, authenticate, identity) |
Nota: En aplicaciones reales deberías usar una base de datos para usuarios y hashing seguro.
3.4 Proteger rutas con JWT
Agrega el decorador @jwt_required()
a las rutas que quieres proteger. Por ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Item(Resource): @jwt_required() def get(self, name): # código igual @jwt_required() def post(self, name): # código igual # Lo mismo para put/delete class ItemList(Resource): @jwt_required() def get(self): return {'items': items}, 200 |
3.5 Obteniendo el token JWT
Usa la ruta /auth
que Flask-JWT crea automáticamente para obtener un token:
1 2 |
curl -X POST -H "Content-Type: application/json" -d '{"username":"admin", "password":"password"}' http://localhost:5000/auth |
Respuesta:
1 2 |
{"access_token": "eyJ0eXAiOiJK..."} |
3.6 Consumir endpoints protegidos
Incluye el token en el header Authorization
:
1 2 |
curl -H "Authorization: JWT eyJ0eXAiOiJK..." http://localhost:5000/items |
4. Manejo de Errores en la API
Es vital que la API maneje errores de forma clara y consistente.
4.1 Manejo básico de errores con Flask
Podemos agregar manejadores para errores comunes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@app.errorhandler(404) def not_found(e): return jsonify({'message': 'Recurso no encontrado'}), 404 @app.errorhandler(400) def bad_request(e): return jsonify({'message': 'Solicitud incorrecta'}), 400 @app.errorhandler(500) def internal_error(e): return jsonify({'message': 'Error interno del servidor'}), 500 # Error JWT from flask_jwt import JWTError @app.errorhandler(JWTError) def handle_jwt_error(e): return jsonify({'message': 'Token inválido o expirado'}), 401 |
4.2 Validar entrada JSON
En métodos post
y put
validemos que venga el JSON esperado:
1 2 3 4 |
data = request.get_json(force=True) if not data or 'price' not in data: return {'message': 'El campo price es obligatorio.'}, 400 |
Incorpora esta validación donde sea necesario.
5. Pruebas con Postman
5.1 Obtén token JWT
- Abre Postman.
- Crea una nueva solicitud POST a
http://localhost:5000/auth
. - En la pestaña Body selecciona
raw
y JSON:
1 2 3 4 5 |
{ "username": "admin", "password": "password" } |
- Envía y copia el token
access_token
de la respuesta.
5.2 Probar endpoints protegidos
- En Postman, crea solicitudes GET/POST a tus rutas (
/items
,/item/<name>
). - En Headers agrega:
1 2 |
Authorization: JWT <tu_token_aquí> |
- Para POST/PUT, en Body indica JSON válido.
5.3 Ejemplo de POST para crear un ítem
POST http://localhost:5000/item/phone
Body JSON:
1 2 3 4 |
{ "price": 199.99 } |
Recuerda siempre usar el token para rutas protegidas. Si no lo haces, recibirás un error 401.
6. Buenas Prácticas y Consideraciones Finales
- Nunca expongas la clave secreta (
SECRET_KEY
) en código público. Usa variables de entorno. - Guarda los usuarios y contraseñas cifrados en una base de datos.
- Define una expiración moderada para los tokens.
- Usa HTTPS en producción para proteger las comunicaciones.
- Validar siempre los datos de entrada.
- Maneja errores con mensajes claros y códigos HTTP adecuados.
- Documenta tu API para otros desarrolladores.
Conclusión
Has aprendido a crear una API RESTful segura con Python y Flask, implementando autenticación con JWT para mantener protegidos tus recursos. También viste cómo manejar rutas CRUD, errores comunes y probar tu API con Postman.
Este es un excelente punto de partida para el desarrollo backend Flask para principiantes, y con estas bases puedes ampliar tu API con bases de datos reales, roles de usuario y más características avanzadas.
¡Te animo a que pongas en práctica lo aprendido y sigas explorando el mundo del desarrollo backend seguro!
Si te gustó este tutorial, comparte y síguenos para más contenido que te ayudará a construir APIs seguras y robustas.
¡Feliz codificación!