Mejores Prácticas para Asegurar OAuth en Aplicaciones Web

OAuth 2.0 se ha convertido en el estándar para la autenticación de APIs, pero implementarlo de forma segura sigue siendo un desafío. Con el robo de tokens, flujos obsoletos y vulnerabilidades específicas de navegadores que amenazan diariamente las aplicaciones web, los desarrolladores necesitan orientación clara sobre qué funciona realmente. Este artículo cubre las prácticas de seguridad esenciales de OAuth 2.0 que necesitas en 2025, desde los requisitos de RFC 9700 hasta patrones específicos para SPAs.
Puntos Clave
- Nunca almacenes tokens de OAuth en localStorage o sessionStorage—utiliza almacenamiento en memoria para SPAs
- El flujo Authorization Code con PKCE es obligatorio para todos los clientes bajo OAuth 2.1
- Implementa rotación de refresh tokens y access tokens de corta duración (15-30 minutos)
- Considera el patrón Backend for Frontend (BFF) para mantener los tokens completamente fuera del navegador
Por Qué la Seguridad de OAuth Importa Más Que Nunca
OAuth protege los datos de tus usuarios al eliminar el intercambio de contraseñas entre aplicaciones. En lugar de entregar a aplicaciones de terceros tus credenciales (como entregar las llaves de tu casa), OAuth emite tokens temporales con alcance limitado—más parecido a dar una llave de valet que solo arranca el auto.
Pero aquí está el problema: los tokens son objetivos valiosos. Un access token robado otorga acceso inmediato a la API. Decisiones de implementación deficientes—almacenar tokens en localStorage, usar flujos obsoletos u omitir PKCE—convierten vulnerabilidades menores en brechas importantes.
Riesgos de Seguridad Principales y Cómo Detenerlos
Robo y Almacenamiento de Tokens
Qué no hacer: Almacenar tokens en localStorage o sessionStorage. Cualquier ataque XSS puede leer estos valores y exfiltrarlos a servidores controlados por atacantes.
Qué hacer: Para SPAs, mantén los tokens solo en memoria. Para aplicaciones del lado del servidor, almacénalos en sesiones cifradas del lado del servidor. Utiliza access tokens de corta duración (15-30 minutos) para limitar el daño de cualquier robo.
Flujos Obsoletos a Evitar
El flujo Implicit está muerto. Tanto RFC 9700 como OAuth 2.1 lo prohíben. ¿Por qué? Porque envía tokens directamente en fragmentos de URL, exponiéndolos al historial del navegador, encabezados de referencia y cualquier JavaScript en la página.
El flujo Resource Owner Password Credentials también debe evitarse—anula todo el propósito de OAuth al requerir que las aplicaciones manejen contraseñas de usuario directamente.
Siempre usa: Authorization Code Flow con PKCE para todos los clientes, incluyendo SPAs y aplicaciones móviles.
Discover how at OpenReplay.com.
Estándares Modernos: RFC 9700 y OAuth 2.1
PKCE Ahora Es Obligatorio
PKCE (Proof Key for Code Exchange) previene ataques de intercepción de códigos de autorización. Así es como funciona:
// Generate code verifier and challenge
const verifier = generateRandomString(128);
const challenge = base64url(sha256(verifier));
// Include challenge in authorization request
const authUrl = `https://auth.example.com/authorize?` +
`client_id=app123&` +
`code_challenge=${challenge}&` +
`code_challenge_method=S256`;
// Send verifier when exchanging code for token
const tokenResponse = await fetch('/token', {
method: 'POST',
body: JSON.stringify({
code: authorizationCode,
code_verifier: verifier
})
});
OAuth 2.1 hace que PKCE sea obligatorio para todos los flujos de código de autorización, no solo para clientes públicos.
Vinculación de Tokens con mTLS o DPoP
La vinculación de tokens asegura que los tokens robados no puedan ser utilizados por atacantes. Dos enfoques principales:
- mTLS (Mutual TLS): Vincula tokens a certificados de cliente
- DPoP (Demonstrating Proof of Possession): Utiliza prueba criptográfica sin certificados
Ambos previenen ataques de repetición de tokens al vincular criptográficamente los tokens al cliente legítimo.
Rotación de Refresh Tokens
Nunca reutilices refresh tokens. Cada actualización debe emitir un nuevo refresh token e invalidar el anterior. Esto limita la ventana para el abuso de refresh tokens robados:
// Server-side refresh token handling
async function refreshAccessToken(oldRefreshToken) {
// Validate and revoke old refresh token
await revokeToken(oldRefreshToken);
// Issue new token pair
return {
access_token: generateAccessToken(),
refresh_token: generateRefreshToken(), // New refresh token
expires_in: 1800
};
}
Seguridad OAuth en SPAs: Consideraciones Especiales
Las aplicaciones de página única enfrentan desafíos únicos ya que todo el código se ejecuta en el navegador. El navegador es territorio hostil—asume que cualquier dato allí puede estar comprometido.
Patrón Backend for Frontend (BFF)
El enfoque más seguro mantiene los tokens completamente fuera del navegador. Un backend proxy ligero maneja los flujos OAuth y mantiene los tokens del lado del servidor, utilizando cookies seguras, httpOnly, sameSite para la sesión de la SPA.
Patrón Token Handler
Para equipos que desean los beneficios de SPA sin la complejidad del backend, el patrón Token Handler proporciona un punto medio. Utiliza un proxy especializado que:
- Maneja flujos OAuth
- Almacena tokens de forma segura
- Emite cookies de sesión de corta duración a la SPA
- Traduce solicitudes autenticadas por cookie a llamadas API autenticadas por token
Si Debes Almacenar Tokens en el Navegador
Cuando BFF no es viable:
- Almacena tokens solo en memoria, nunca en localStorage
- Usa service workers para aislar el acceso a tokens
- Implementa expiración agresiva de tokens (5-15 minutos)
- Nunca almacenes refresh tokens en el navegador
Lista de Verificación de Implementación
✓ Usa Authorization Code Flow con PKCE para todos los clientes
✓ Implementa coincidencia exacta de URI de redirección
✓ Establece duraciones de tokens al mínimo viable
✓ Habilita rotación de refresh tokens para clientes públicos
✓ Usa el parámetro state para protección CSRF
✓ Implementa vinculación de tokens (mTLS/DPoP) para aplicaciones de alta seguridad
✓ Para SPAs: Considera patrones BFF o Token Handler
✓ Monitorea requisitos de cumplimiento de OAuth 2.1
Conclusión
Asegurar OAuth en aplicaciones web requiere comprender tanto las fortalezas del protocolo como las amenazas específicas que enfrenta tu arquitectura. Comienza con los requisitos de RFC 9700: PKCE obligatorio, sin flujo implicit y manejo adecuado de tokens. Para SPAs, considera seriamente mantener los tokens completamente fuera del navegador mediante patrones BFF o Token Handler. Estas no son solo mejores prácticas—son el estándar mínimo para la seguridad de OAuth en 2025.
Preguntas Frecuentes
No. Incluso las aplicaciones sin datos sensibles no deben usar localStorage para tokens. Los tokens robados pueden usarse para tomar control de cuentas, abusar de APIs y como trampolines para ataques más serios. Siempre almacena tokens en memoria o usa sesiones del lado del servidor.
Sí. OAuth 2.1 hace obligatorio PKCE para todos los flujos de código de autorización, incluyendo clientes confidenciales. PKCE añade defensa en profundidad contra ataques de intercepción de códigos de autorización que los client secrets por sí solos no pueden prevenir, especialmente en escenarios que involucran redes comprometidas o extensiones de navegador maliciosas.
Usa el patrón Backend for Frontend donde tu backend gestiona los refresh tokens y proporciona a la SPA access tokens de corta duración mediante cookies seguras. Alternativamente, usa autenticación silenciosa con prompt=none para obtener nuevos tokens sin interacción del usuario cuando expire el access token.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.