Definición
¿Has usado alguna vez una tarjeta regalo? Quien la tenga puede gastarla - no pide DNI, no verifica que seas quien la compró. Un bearer token (token al portador) funciona igual: quien lo posea puede usarlo para acceder a recursos protegidos, sin necesidad de demostrar identidad adicional. El token mismo ES la autorización.
Este modelo es el más común en APIs modernas. Cuando te autenticas con OAuth, recibes un access token. Para acceder a recursos protegidos, incluyes ese token en el header “Authorization: Bearer eyJhbG…”. El servidor ve el token, lo valida (¿firma correcta? ¿no expirado? ¿scopes suficientes?) y te da acceso. No pregunta “¿eres realmente tú?” - si tienes el token válido, entras.
¿Por qué este modelo tan “peligroso”? Por simplicidad y rendimiento. No necesitas establecer una sesión, no hay ida y vuelta extra para verificar identidad. El token contiene toda la información necesaria para la autorización. Pero esto significa que proteger el token es CRÍTICO - si alguien lo roba, puede usarlo como si fuera tú hasta que expire o se revoque.
Ejemplo
Aplicaciones Móviles con APIs: Tu app de banking móvil guarda un bearer token después del login. Cada vez que consultas saldo, haces transferencias, o revisas movimientos, la app envía ese token. El servidor confía en el token sin pedirte contraseña de nuevo - la sesión se mantiene hasta que el token expira.
Single Page Applications (SPAs): Una aplicación React obtiene un bearer token al iniciar sesión. Lo guarda en memoria (no localStorage por seguridad) y lo incluye en cada petición a la API. Si cierras la pestaña, el token se pierde y tienes que volver a autenticarte.
Integraciones entre Servicios: Tu servidor backend tiene un bearer token para llamar a la API de Stripe. Cada vez que procesa un pago, incluye ese token. Stripe confía en que quien tenga ese token está autorizado para operar en tu cuenta.
CI/CD y Automatización: Los pipelines de GitHub Actions usan bearer tokens (secrets) para desplegar a servicios cloud. El token permite al pipeline actuar en nombre de tu cuenta sin intervención humana.
Analogía
El Dinero en Efectivo: Quien tiene el billete de 50 euros puede gastarlo. El cajero no pregunta de dónde lo sacaste ni si eres su dueño original. El billete mismo es la autorización para gastar ese valor. Si lo pierdes, quien lo encuentre puede usarlo.
La Llave del Coche: Cualquiera con la llave puede abrir y arrancar el coche. El coche no verifica tu identidad - solo que tengas la llave correcta. Por eso cuidas tanto tus llaves y usas sistemas de bloqueo adicionales.
El Ticket del Guardarropa: Te dan un ticket numerado por tu abrigo. Cualquiera que presente ese ticket recibe tu abrigo - el encargado no pide DNI. El ticket es la prueba de “propiedad” temporal. Si lo pierdes, tienes un problema.
La Tarjeta de Acceso sin Foto: Tu badge de acceso al parking solo tiene un código de barras. Cualquiera que lo escanee puede entrar. No hay verificación facial ni biométrica - la tarjeta misma es la autorización.
Code Example
// Cliente: Usando un bearer token
const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...';
fetch('https://api.example.com/protected', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
// Servidor: Verificando bearer token
function verifyBearerToken(req, res, next) {
const authHeader = req.headers.authorization;
// Verificar formato del header
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({
error: 'Token no proporcionado',
hint: 'Incluir header: Authorization: Bearer <token>'
});
}
// Extraer el token (después de "Bearer ")
const token = authHeader.substring(7);
try {
// Validar el token (JWT en este ejemplo)
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.miapp.com',
audience: 'https://api.miapp.com'
});
// Verificar que no está en blacklist (tokens revocados)
if (isTokenRevoked(decoded.jti)) {
return res.status(401).json({ error: 'Token revocado' });
}
req.user = decoded;
next();
} catch (error) {
if (error.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Token expirado' });
}
return res.status(401).json({ error: 'Token inválido' });
}
}
Diagrama
sequenceDiagram
participant Cliente as Cliente
participant API
participant Atacante as Atacante
Note over Cliente: Tiene bearer token válido
Cliente->>API: Authorization: Bearer eyJhbG...
API->>API: Token válido? SÍ
API->>Cliente: 200 OK - Datos protegidos
Note over Cliente,Atacante: Si el token es robado...
Cliente-->>Atacante: Token interceptado o filtrado
Atacante->>API: Authorization: Bearer eyJhbG...
API->>API: Token válido? SÍ
API->>Atacante: 200 OK - Datos protegidos
Note over API,Atacante: El servidor no puede distinguir
usuario legítimo de atacante!
rect rgb(255, 230, 230)
Note over Cliente,Atacante: RIESGO: Quien PORTA el token tiene acceso
end
Notas de Seguridad
CRÍTICO - …
Configuración y Validación:
- Transmite SOLO sobre HTTPS para prevenir intercepción; un token capturado da acceso completo.
- Almacena de forma segura según el contexto: en memoria para SPAs (nunca localStorage), cookies httpOnly con Secure y SameSite para web tradicional, almacenamiento encriptado (Keychain/Keystore) para móviles.
- Implementa tiempos de expiración cortos (15 minutos a 1 hora) para limitar la ventana de exposición.
- NUNCA expongas tokens en URLs - quedan registrados en logs del servidor, historial del navegador, y encabezados Referer.
- Valida completamente el token en cada petición incluyendo firma, expiración, issuer y audience.
Monitoreo y Protección:
- Implementa revocación de tokens para logout y compromiso de cuentas mediante blacklist o invalidación de firma.
- Usa rotación de refresh tokens para sesiones largas.
- Monitorea patrones de uso anómalos como mismo token desde múltiples IPs simultáneas.
- Considera token binding para vincular tokens a dispositivos específicos.
- NUNCA registres bearer tokens en logs de aplicación o infraestructura.