🔐 Autenticación con JWT en PHP explicada fácil (con ejemplos reales)
Introducción
Cuando empiezas a crear APIs, hay un momento donde todo cambia:
👉 ya no basta con devolver datos
👉 necesitas controlar quién puede acceder
Y aquí es donde entra uno de los conceptos más importantes en backend moderno:
JWT (JSON Web Token)
JWT se usa en:
- APIs REST
- apps móviles
- dashboards
- SaaS
- microservicios
- autenticación moderna
Pero aquí está el problema:
Muchos tutoriales te enseñan a copiar código…
pero no a entender cómo funciona.
En este post vas a aprender:
- qué es JWT realmente
- cómo funciona por dentro
- cómo generar tokens en PHP
- cómo validar tokens
- cómo proteger rutas
- errores comunes
- buenas prácticas
👉 todo explicado de forma clara y práctica
🧠 Qué es JWT (explicado fácil)
JWT es un token que representa la identidad de un usuario.
En lugar de usar sesiones en servidor, haces esto:
- el usuario hace login
- el servidor genera un token
- el cliente guarda ese token
- el cliente lo envía en cada petición
- el servidor valida el token
👉 Si es válido → acceso permitido
👉 Si no → acceso denegado
📦 Estructura de un JWT
Un token tiene 3 partes:
HEADER.PAYLOAD.SIGNATURE
Ejemplo:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
🔍 Qué contiene cada parte
1. Header
Define el algoritmo:
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload (datos)
Aquí va la info del usuario:
{
"user_id": 1,
"email": "irak@mail.com",
"exp": 1710000000
}
👉 Importante: esto no está cifrado
3. Signature
Se genera con:
- header
- payload
- clave secreta
👉 Sirve para evitar manipulación
⚙️ Cómo implementar JWT en PHP
📦 Paso 1: instalar librería
La más usada:
composer require firebase/php-jwt
🔑 Paso 2: generar token (login)
<?php
use Firebase\JWT\JWT;
$key = "mi_clave_secreta";
$payload = [
"user_id" => 1,
"email" => "irak@mail.com",
"exp" => time() + 3600 // 1 hora
];
$jwt = JWT::encode($payload, $key, 'HS256');
echo json_encode([
"token" => $jwt
]);
🔍 Paso 3: validar token
<?php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$headers = getallheaders();
if (!isset($headers['Authorization'])) {
http_response_code(401);
exit("Token requerido");
}
$token = str_replace('Bearer ', '', $headers['Authorization']);
try {
$decoded = JWT::decode($token, new Key($key, 'HS256'));
echo json_encode([
"message" => "Acceso permitido",
"user" => $decoded
]);
} catch (Exception $e) {
http_response_code(401);
echo json_encode(["error" => "Token inválido"]);
}
🔐 Cómo proteger rutas con JWT
Ejemplo:
require 'auth.php'; // valida token
👉 Si el token falla → no pasa
👉 Si es válido → continúa
📡 Cómo enviar el token desde frontend
Ejemplo con fetch:
fetch('/api/protegido', {
headers: {
"Authorization": "Bearer TOKEN_AQUI"
}
})
⚠️ Errores comunes con JWT
❌ Guardar datos sensibles en el payload
👉 cualquiera puede leerlo
❌ No validar expiración
👉 riesgo de seguridad
❌ Usar clave débil
👉 fácil de romper
❌ No usar HTTPS
👉 token puede ser interceptado
🔐 Buenas prácticas
- usar claves seguras
- usar expiración corta
- refrescar tokens si hace falta
- no guardar passwords en JWT
- usar HTTPS siempre
🧠 JWT vs sesiones (muy importante)
JWT Sesión stateless stateful no guarda en servidor sí escalable más simple ideal APIs ideal apps clásicas
🧪 Ejemplo real de flujo completo
- Usuario login → API genera token
- Frontend guarda token
- Usuario hace request
- API valida token
- Devuelve datos
📈 Cuándo usar JWT
✔ APIs
✔ apps móviles
✔ microservicios
✔ SPA
❌ Cuándo NO usar JWT
- apps simples
- sin necesidad de escalabilidad
- proyectos muy pequeños
🧩 Conclusión:
JWT es una de las herramientas más importantes en backend moderno.
Si lo entiendes:
- puedes proteger APIs
- puedes escalar sistemas
- puedes trabajar en proyectos reales
Y eso te pone en otro nivel.