20-El token
Los datos van en el body de la petición y el token va en el header por separado.
✅ CORRECTO: El token solo contiene información de autenticación (quién eres), no los datos de tu petición.
✅ INCORRECTO: Los registros NO van dentro del token.
Flujo detallado:
1. Login (obtener token)
POST /login
Body: { "email": "usuario@ejemplo.com", "password": "123456" }2. Servidor responde con token
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0IiwiaWF0IjoxNj...",
"user": { "id": 1234, "name": "Juan" }
}3. Peticiones posteriores (con token)
POST /guardar-registro
Headers: {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"Content-Type": "application/json"
}
Body: {
"producto": "Laptop",
"precio": 999.99,
"cantidad": 5
}¿Qué contiene el token?
Típicamente información de identificación:
{
"userId": "1234",
"username": "juan123",
"iat": 1627837283, // Fecha de emisión
"exp": 1627840883 // Fecha de expiración
}Ventajas de este enfoque:
Stateless: El servidor no guarda sesiones
Escalable: Fácil de manejar en múltiples servidores
Seguro: El token puede tener expiración y firma digital
¿Te queda claro cómo separamos la autenticación (header) de los datos (body)?
¡Exacto! 🎯 Has entendido perfectamente. Así es exactamente como funciona:
Flujo correcto:
1. Registro/Login (Cliente → Servidor)
POST /auth/login
Body: {
"email": "usuario@ejemplo.com",
"password": "mi_password"
}2. Respuesta del Servidor (Servidor → Cliente)
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 123,
"name": "Juan Pérez",
"email": "usuario@ejemplo.com"
}
}3. Peticiones posteriores (Cliente → Servidor)
POST /api/guardar-producto
Headers: {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"Content-Type": "application/json"
}
Body: {
"nombre": "Laptop Gamer",
"precio": 1500,
"categoria": "Tecnología"
}¿Qué hace el servidor con el token?
Recibe la petición con el token en el header
AuthorizationVerifica que el token sea válido y esté firmado por él mismo
Extrae la información del usuario (ej:
userId: 123)Procesa los datos del body usando la identidad del usuario
Responde al cliente
Ejemplo en código (Node.js/Express):
// Middleware para verificar token
const verifyToken = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Token requerido' });
}
try {
// Verificar y decodificar token
const decoded = jwt.verify(token, 'clave_secreta');
req.user = decoded; // Agregar info del usuario a la request
next(); // Continuar con la ruta
} catch (error) {
return res.status(403).json({ error: 'Token inválido' });
}
};
// Ruta protegida
app.post('/api/guardar-producto', verifyToken, (req, res) => {
// req.user contiene la info del token (ej: { userId: 123 })
// req.body contiene los datos del producto
const nuevoProducto = {
...req.body,
usuarioId: req.user.userId, // Relacionar con el usuario
fechaCreacion: new Date()
};
// Guardar en base de datos...
console.log('Producto guardado:', nuevoProducto);
res.json({ success: true, producto: nuevoProducto });
});Resumen final:
✅ Token en headers: Autenticación (¿quién eres?)
✅ Datos en body: Información de la petición (¿qué quieres hacer?)
✅ Separación clara: Seguridad y organización
¡Perfecto! Ahora tienes claro el concepto. ¿Te gustaría ver algún ejemplo específico o tienes otra duda? 😊
Exactamente! 🎯 Lo has entendido perfectamente. Así es como funciona paso a paso:
Flujo completo y correcto:
1. Registro inicial (Crear cuenta)
POST /auth/register
Body: {
"email": "usuario@ejemplo.com",
"password": "mi_password_123",
"name": "Juan Pérez"
}El servidor guarda tu usuario y contraseña (encriptada) en la base de datos
Todavía no hay token
2. Login (Obtener token)
POST /auth/login
Body: {
"email": "usuario@ejemplo.com",
"password": "mi_password_123"
}✅ Servidor verifica que las credenciales sean correctas
✅ Genera el token con información como:
{
"userId": "123",
"email": "usuario@ejemplo.com",
"iat": 1627837283, // Fecha de creación
"exp": 1627840883 // Fecha de expiración (ej: 1 hora)
}✅ Firma el token con una clave secreta que solo el servidor conoce
✅ Envía el token al cliente
3. Peticiones con token
GET /api/mis-datos
Headers: {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}🔍 Servidor verifica:
¿El token está bien formado?
¿La firma es válida? (¿lo firmé yo?)
¿No ha expirado?
¿El usuario todavía existe?
4. Procesamiento
Si TODO ES VÁLIDO: Procesa tu petición y te responde
Si ALGO FALLA: Retorna error
401 Unauthorizedo403 Forbidden
Ejemplo de verificación en el servidor:
const jwt = require('jsonwebtoken');
const CLAVE_SECRETA = 'mi_clave_super_secreta';
// Middleware de verificación
function verificarToken(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'Token requerido' });
}
try {
// Verificar y decodificar el token
const decoded = jwt.verify(token, CLAVE_SECRETA);
// decoded = { userId: "123", email: "usuario@ejemplo.com", iat: 1627837283, exp: 1627840883 }
req.usuario = decoded; // Agregar info del usuario a la request
next(); // Continuar con la petición
} catch (error) {
return res.status(403).json({ error: 'Token inválido o expirado' });
}
}
// Uso en una ruta protegida
app.get('/api/mis-datos', verificarToken, (req, res) => {
// Solo llega aquí si el token es válido
console.log('Usuario autenticado:', req.usuario.userId);
// Procesar la petición...
});¿Qué pasa si alguien modifica el token?
Si un cliente intenta modificar el token (ej: cambiar userId: 123 por userId: 456):
La firma digital dejará de coincidir
jwt.verify()fallará inmediatamenteEl servidor rechazará la petición
Resumen:
✅ Credenciales correctas → Servidor genera y firma token
✅ Cliente envía token en headers + datos en body
✅ Servidor verifica firma y validez
✅ Si todo ok → Procesa la petición
❌ Si algo falla → Rechaza la petición
¡Perfecto! Ahora sí tienes el concepto 100% claro. ¿Te queda alguna duda?
Te muestro un ejemplo completo en PHP:
1. Instalación necesaria
composer require firebase/php-jwt2. Login - Generar Token
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class AuthController {
// ¡ESTA CLAVE DEBE SER SECRETA Y SEGURA!
private $clave_secreta = "mi_clave_super_secreta_2024";
public function login($email, $password) {
// 1. Verificar credenciales en la base de datos
$usuario = $this->verificarCredenciales($email, $password);
if (!$usuario) {
return ["error" => "Credenciales inválidas"];
}
// 2. Datos para incluir en el token
$payload = [
"iss" => "mi-servidor.com", // Emisor
"aud" => "mi-aplicacion", // Audiencia
"iat" => time(), // Fecha de emisión
"exp" => time() + (60*60), // Expira en 1 hora
"data" => [ // Datos del usuario
"userId" => $usuario['id'],
"email" => $usuario['email'],
"name" => $usuario['name']
]
];
// 3. Generar token firmado
$jwt = JWT::encode($payload, $this->clave_secreta, 'HS256');
return [
"token" => $jwt,
"user" => [
"id" => $usuario['id'],
"name" => $usuario['name'],
"email" => $usuario['email']
]
];
}
private function verificarCredenciales($email, $password) {
// Simulación de verificación en BD
$usuarios = [
[
'id' => 1,
'email' => 'usuario@ejemplo.com',
'password' => password_hash('password123', PASSWORD_DEFAULT),
'name' => 'Juan Pérez'
]
];
foreach ($usuarios as $usuario) {
if ($usuario['email'] === $email &&
password_verify($password, $usuario['password'])) {
return $usuario;
}
}
return false;
}
}
?>3. Middleware para verificar token
<?php
function verificarToken() {
$clave_secreta = "mi_clave_super_secreta_2024";
// Obtener token del header
$headers = apache_request_headers();
if (!isset($headers['Authorization'])) {
http_response_code(401);
echo json_encode(["error" => "Token no proporcionado"]);
exit;
}
$authHeader = $headers['Authorization'];
$token = str_replace('Bearer ', '', $authHeader);
try {
// Verificar y decodificar el token
$decoded = JWT::decode($token, new Key($clave_secreta, 'HS256'));
return $decoded;
} catch (Exception $e) {
http_response_code(403);
echo json_encode(["error" => "Token inválido: " . $e->getMessage()]);
exit;
}
}
?>4. Ruta protegida
<?php
// Ejemplo de endpoint protegido
header('Content-Type: application/json');
// Verificar token
$usuarioAutenticado = verificarToken();
// Si llegó aquí, el token es válido
$datosPeticion = json_decode(file_get_contents('php://input'), true);
// Procesar la petición
$response = [
"success" => true,
"message" => "Petición procesada correctamente",
"usuario" => $usuarioAutenticado->data,
"datosRecibidos" => $datosPeticion
];
echo json_encode($response);
?>5. Ejemplo de uso desde cliente
<?php
// Cliente haciendo petición con token
$token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."; // Token recibido en login
$data = [
"producto" => "Laptop Gamer",
"precio" => 1500,
"cantidad" => 2
];
$options = [
'http' => [
'header' => [
"Authorization: Bearer " . $token,
"Content-Type: application/json"
],
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents('http://tuservidor.com/api/guardar-producto', false, $context);
echo $result;
?>¡IMPORTANTE! Sobre la clave secreta:
✅ Sí, tú proporcionas la clave secreta
✅ Debe ser una cadena larga y compleja (mínimo 32 caracteres)
✅ Nunca la expongas en código público
✅ Guárdala en variables de entorno
✅ Usa diferentes claves para entornos de desarrollo y producción
Recomendación para clave segura:
// En producción, usa variables de entorno
$clave_secreta = getenv('JWT_SECRET_KEY');
// O genera una clave segura:
$clave_secreta = bin2hex(random_bytes(32)); // 64 caracteres hexadecimales
Comentarios
Publicar un comentario