Command Palette

Search for a command to run...

OAuth 2.0: Autenticación Delegada Segura en JavaScript

Aprende qué es OAuth 2.0, cómo funciona el flujo de autorización, y las mejores prácticas para implementar autenticación segura con OAuth en tus aplicaciones JavaScript.

Lectura: 16 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • OAuth 2.0 es un estándar de autorización que permite que aplicaciones accedan a recursos en nombre de usuarios
  • El flujo de autorización involucra el usuario, el cliente, el servidor de autorización y el servidor de recursos
  • Los tokens de acceso tienen tiempos de vida limitados y deben renovarse usando refresh tokens
  • Usa siempre HTTPS para proteger el flujo de autorización y evitar interceptación de tokens
  • Implementa PKCE (Proof Key for Code Exchange) para aplicaciones públicas y SPA

Introducción a OAuth

OAuth 2.0 es un estándar de autorización que permite que aplicaciones de terceros accedan a recursos del usuario sin compartir sus credenciales. En lugar de que el usuario proporcione su nombre de usuario y contraseña a cada aplicación, OAuth permite que el usuario autorice a una aplicación para acceder a sus recursos en otra aplicación. Esto es especialmente útil para integraciones con servicios como Google, Facebook, Twitter, y GitHub.

OAuth 2.0 define varios flujos de autorización para diferentes escenarios: aplicaciones web, aplicaciones móviles, aplicaciones de escritorio, y dispositivos sin navegador. El flujo más común es el Authorization Code Flow, que se usa para aplicaciones web y SPA (Single Page Applications). Este flujo involucra redirecciones del usuario entre el cliente, el servidor de autorización, y el servidor de recursos, intercambiando códigos de autorización por tokens de acceso.

Ventajas de OAuth sobre Autenticación Tradicional

OAuth ofrece varias ventajas sobre la autenticación tradicional: los usuarios no comparten sus credenciales con aplicaciones de terceros, pueden revocar el acceso de forma centralizada, y las aplicaciones no necesitan almacenar contraseñas de usuarios, reduciendo el riesgo de violaciones de seguridad.

Cómo Funciona OAuth

OAuth 2.0 funciona mediante un protocolo de autorización delegada que involucra cuatro roles principales: el propietario del recurso (el usuario), el cliente (la aplicación que quiere acceder a los recursos), el servidor de autorización (como Google o Facebook), y el servidor de recursos (la API que proporciona los datos). El flujo comienza cuando el cliente solicita acceso a los recursos del usuario, lo que inicia un proceso de autorización donde el usuario aprueba o deniega el acceso.

  • <strong>Resource Owner:</strong> El usuario que posee los datos y puede autorizar el acceso
  • <strong>Client:</strong> La aplicación que solicita acceso a los recursos del usuario
  • <strong>Authorization Server:</strong> El servidor que emite tokens de acceso después de autorizar al usuario
  • <strong>Resource Server:</strong> La API que proporciona los datos protegidos con los tokens de acceso
oauth-flujo.js
Loading code...

Este ejemplo muestra el flujo básico de OAuth 2.0. El cliente redirige al usuario al servidor de autorización, el usuario autoriza el acceso, el servidor de autorización redirige de vuelta al cliente con un código de autorización, y el cliente intercambia el código por un token de acceso que puede usar para acceder a los recursos del usuario.

Advertencia: OAuth No es Autenticación

OAuth es un protocolo de autorización, no de autenticación. OAuth no verifica la identidad del usuario, solo autoriza el acceso a recursos. Para autenticación, debes usar OpenID Connect (OIDC), que se construye sobre OAuth 2.0 y añade autenticación estándar.

Flujo de Autorización OAuth 2.0

El flujo de autorización OAuth 2.0 Authorization Code es el más usado para aplicaciones web y SPA. Este flujo es seguro porque el código de autorización solo se transmite a través del frontend del navegador, mientras que el intercambio del código por el token de acceso ocurre en el servidor del cliente, donde las credenciales del cliente (client_id y client_secret) están protegidas.

Paso 1: Solicitud de Autorización

El cliente inicia el flujo redirigiendo al usuario al endpoint de autorización del servidor de autorización. Esta redirección incluye parámetros como response_type (siempre code para Authorization Code Flow), client_id (identificador del cliente), redirect_uri (URL donde el servidor de autorización redirigirá después de la autorización), scope (permisos solicitados), y state (valor aleatorio para prevenir CSRF).

oauth-paso1.js
Loading code...

Este código muestra cómo construir la URL de autorización y redirigir al usuario. El parámetro state es un valor aleatorio que se usa para prevenir ataques CSRF. El servidor de autorización redirigirá de vuelta al cliente con el mismo valor de state, permitiendo que el cliente verifique que la respuesta es legítima.

Paso 2: Autorización del Usuario

El usuario llega al servidor de autorización y ve una pantalla de autorización donde se le solicita que apruebe o deniegue el acceso del cliente a sus recursos. Esta pantalla muestra qué permisos solicita el cliente (scope), el nombre del cliente, y puede incluir información adicional sobre qué recursos se accederán. El usuario puede aprobar todos los permisos, algunos, o denegar el acceso completamente.

oauth-paso2.js
Loading code...

Este código muestra cómo manejar la redirección de vuelta del servidor de autorización. El cliente verifica que el parámetro state coincide con el valor enviado originalmente, previniendo ataques CSRF. Si el usuario denegó el acceso, el cliente muestra un mensaje de error. Si el usuario aprobó el acceso, el cliente procede al siguiente paso.

Paso 3: Intercambio de Código por Token

Después de que el usuario aprueba el acceso, el servidor de autorización redirige al cliente con un código de autorización. El cliente entonces hace una solicitud POST al endpoint de token del servidor de autorización, intercambiando el código de autorización por un token de acceso. Esta solicitud ocurre en el servidor del cliente, donde las credenciales del cliente (client_id y client_secret) están protegidas.

oauth-paso3.js
Loading code...

Este código muestra cómo intercambiar el código de autorización por un token de acceso. La solicitud incluye el grant_type (authorization_code), el code (código de autorización), el redirect_uri (debe coincidir con el usado en el paso 1), y las credenciales del cliente. El servidor de autorización valida estos parámetros y devuelve un token de acceso y opcionalmente un refresh token.

Mejor Práctica: Usar PKCE para Aplicaciones Públicas

Para aplicaciones públicas (SPA, aplicaciones móviles) que no pueden mantener el client_secret seguro, usa PKCE (Proof Key for Code Exchange). PKCE añade un code_verifier y un code_challenge al flujo, previniendo que atacantes intercepten el código de autorización y lo usen para obtener tokens de acceso.

Implementación del Cliente OAuth

Implementar un cliente OAuth en JavaScript requiere manejar el flujo de autorización completo, desde la solicitud inicial hasta el intercambio del código por el token. Puedes usar librerías como passport.js o implementar el flujo manualmente usando fetch o axios. La implementación debe manejar errores, redirecciones, y el almacenamiento seguro de tokens.

Cliente OAuth con Express.js

Para implementar un cliente OAuth en Express.js, puedes usar passport.js con estrategias OAuth. Passport.js simplifica el manejo del flujo de autorización, proporcionando middleware para proteger rutas y funciones para iniciar y cerrar sesión. Configurar passport.js requiere especificar el client_id, client_secret, callback URL, y los scopes solicitados.

oauth-express.js
Loading code...

Este código muestra cómo configurar passport.js con la estrategia OAuth de Google. La configuración incluye el client_id, client_secret, y el callback URL donde el servidor de autorización redirigirá después de la autorización. El middleware de passport.js protege las rutas, verificando que el usuario esté autenticado antes de permitir el acceso.

Cliente OAuth para SPA

Para SPA (Single Page Applications), el flujo de OAuth debe usar PKCE (Proof Key for Code Exchange) para mayor seguridad. PKCE genera un code_verifier aleatorio y un code_challenge derivado del code_verifier. El code_challenge se envía en la solicitud de autorización, y el code_verifier se usa en el intercambio del código por el token, previniendo que atacantes intercepten el código.

oauth-pkce.js
Loading code...

Este código muestra cómo implementar PKCE en una SPA. El code_verifier es un valor aleatorio que se genera en el cliente, y el code_challenge se deriva usando SHA-256 y se envía en la solicitud de autorización. Al intercambiar el código por el token, el code_verifier se envía para verificar que la solicitud es legítima.

Mejor Práctica: Almacenar Tokens de Forma Segura

Almacena los tokens de acceso y refresh tokens de forma segura. Para aplicaciones web, usa cookies HttpOnly y Secure. Para SPA, usa sessionStorage con PKCE. Para aplicaciones móviles, usa el almacenamiento seguro del sistema operativo (Keychain en iOS, Keystore en Android). Nunca almacenes tokens en localStorage sin protección adicional.

Mejores Prácticas de Seguridad

Implementar OAuth de forma segura requiere seguir varias mejores prácticas que van más allá del flujo básico de autorización. Debes considerar cómo se transmiten los tokens, cómo se almacenan, qué permisos solicitas, y cómo manejas la revocación de tokens. Estas prácticas adicionales reducen significativamente el riesgo de vulnerabilidades en tu implementación de OAuth.

  • <strong>Usa siempre HTTPS:</strong> El flujo de autorización debe ocurrir sobre HTTPS para evitar interceptación
  • <strong>Implementa PKCE:</strong> Usa PKCE para aplicaciones públicas y SPA para prevenir interceptación de códigos
  • <strong>Valida el parámetro state:</strong> Usa valores aleatorios para state y verifica que coincidan para prevenir CSRF
  • <strong>Solicita permisos mínimos:</strong> Solo solicita los scopes necesarios para tu aplicación
  • <strong>Implementa revocación:</strong> Permite que los usuarios revoken el acceso desde tu aplicación
oauth-seguro.js
Loading code...

Este código muestra una implementación segura de OAuth con múltiples capas de protección. Implementa PKCE para prevenir interceptación de códigos, valida el parámetro state para prevenir CSRF, y usa HTTPS para todas las comunicaciones.

Protección Contra Ataques Comunes

Implementa protección contra ataques comunes como CSRF usando el parámetro state con valores aleatorios, contra interceptación de códigos usando PKCE, y contra token theft usando almacenamiento seguro de tokens y tiempos de expiración cortos.

Errores Comunes en OAuth

Al implementar OAuth, los desarrolladores cometen errores que pueden comprometer la seguridad de la aplicación. Conocer estos errores comunes te ayudará a evitarlos y a implementar una autorización OAuth robusta y segura.

Error 1: No Validar el Parámetro State

Un error común es no implementar o validar el parámetro state en el flujo de OAuth. El parámetro state es un valor aleatorio que se envía en la solicitud de autorización y se devuelve en la respuesta. Sin validar que el state devuelto coincide con el enviado originalmente, tu aplicación es vulnerable a ataques CSRF donde un atacante puede engañar a usuarios para autorizar acceso sin su conocimiento.

error-sin-state.js
Loading code...

Este código muestra el error de no validar el parámetro state. Un atacante puede iniciar el flujo de autorización y engañar a un usuario para autorizar el acceso. Cuando el servidor de autorización redirige de vuelta, el atacante recibe el código de autorización y puede obtener tokens de acceso.

Error 2: No Usar PKCE en Aplicaciones Públicas

Otro error común es no implementar PKCE en aplicaciones públicas como SPA o aplicaciones móviles. Sin PKCE, un atacante que intercepta el código de autorización puede usarlo para obtener tokens de acceso, ya que el código de autorización se transmite a través del frontend del navegador donde puede ser interceptado. PKCE añade un code_verifier que solo el cliente legítimo conoce, previniendo este ataque.

error-sin-pkce.js
Loading code...

Este código muestra el error de no implementar PKCE en una SPA. Un atacante puede interceptar el código de autorización y usarlo para obtener tokens de acceso. La solución es implementar PKCE, generando un code_verifier aleatorio y un code_challenge derivado.

Error 3: Almacenar Tokens de Forma Insegura

Almacenar tokens de acceso en localStorage o sessionStorage sin protección adicional es un error grave que permite que scripts maliciosos o ataques XSS roben los tokens. Los tokens deben almacenarse de forma segura, usando cookies HttpOnly y Secure para aplicaciones web, o el almacenamiento seguro del sistema operativo para aplicaciones móviles.

error-almacenamiento-inseguro.js
Loading code...

Este código muestra el error de almacenar tokens en localStorage. Un atacante que explota una vulnerabilidad XSS puede leer el localStorage y robar los tokens de acceso. La solución es usar cookies HttpOnly y Secure, que no son accesibles desde JavaScript.

Resumen: OAuth 2.0

Conceptos principales:

  • OAuth 2.0 es un estándar de autorización que permite que aplicaciones accedan a recursos en nombre de usuarios
  • El flujo de autorización involucra el usuario, el cliente, el servidor de autorización y el servidor de recursos
  • Los tokens de acceso tienen tiempos de vida limitados y deben renovarse usando refresh tokens
  • PKCE (Proof Key for Code Exchange) protege aplicaciones públicas contra interceptación de códigos
  • El parámetro state previene ataques CSRF en el flujo de autorización

Mejores prácticas:

  • Usa siempre HTTPS para proteger el flujo de autorización y evitar interceptación de tokens
  • Implementa PKCE para aplicaciones públicas y SPA para mayor seguridad
  • Valida el parámetro state con valores aleatorios para prevenir CSRF
  • Solicita permisos mínimos necesarios para tu aplicación
  • Almacena tokens de forma segura usando cookies HttpOnly o almacenamiento seguro del sistema operativo