⏱️ Lectura: 15 min

Cada vez que tocás “Continuar con Google” en una app nueva y nunca escribís una contraseña, estás usando OAuth 2.0. El protocolo se formalizó en el RFC 6749 en octubre de 2012 y hoy sostiene casi todo inicio de sesión delegado de la web.

📑 En este artículo
  1. TL;DR
  2. ¿Qué es OAuth 2.0?
  3. Por qué importa el estándar de autorización abierta
  4. Cómo funciona el flujo de autorización delegada
  5. Ejemplos prácticos: cómo empezar con OAuth2
    1. Paso 1: construir la URL de autorización
    2. Paso 2: intercambiar el código por un token
    3. Paso 3: llamar a la API con el token
    4. Paso 4: verificar el scope otorgado
  6. Casos de uso reales
  7. Errores comunes y buenas prácticas
  8. Comparativa: OAuth2 frente a otros estándares de autorización
  9. Profundizando: PKCE y el interior del flujo de OAuth2
  10. Preguntas frecuentes
    1. ¿OAuth 2.0 reemplaza las contraseñas por completo?
    2. ¿Qué diferencia a OAuth2 de OpenID Connect?
    3. ¿Sigue siendo seguro el flujo implícito del protocolo de autorización abierta?
    4. ¿Qué es PKCE y por qué lo necesita el flujo de autorización delegada?
    5. ¿Cuánto dura un access token en OAuth2?
    6. ¿Qué pasa si se filtra un refresh token de OAuth2?
  11. Referencias

Entenderlo a fondo evita dos errores frecuentes entre desarrolladores: tratarlo como un sistema de login y copiar ejemplos de flujos ya deprecados. Este artículo explica sus roles, sus flujos vigentes y los errores que más rompen implementaciones reales.

TL;DR

  • OAuth 2.0 separa la identidad de la autorización: una app accede sin ver nunca tu contraseña
  • El authorization code flow con PKCE es el estándar actual para apps web y móviles
  • Los access tokens caducan en minutos; los refresh tokens los renuevan sin pedir login otra vez
  • Confundir OAuth con un protocolo de autenticación es el error más común al implementarlo
  • RFC 6749 define cuatro roles: resource owner, client, authorization server y resource server

¿Qué es OAuth 2.0?

OAuth 2.0 es un protocolo de autorización abierto que permite a una aplicación acceder a datos de un usuario en otro servicio sin manejar ni ver su contraseña. Funciona con tokens temporales emitidos por un servidor de autorización, definidos en el RFC 6749 del IETF desde 2012.

El protocolo distingue cuatro participantes: el usuario que posee los datos, la aplicación que los quiere, el servidor que emite los tokens y el servidor que los acepta para entregar el recurso. Casi todas las APIs públicas actuales (GitHub, Spotify, Slack, Google Cloud) implementan alguna variante de este esquema para que un tercero acceda sin pedir la contraseña original.

A diferencia de lo que mucha gente asume, el protocolo de autorización no verifica identidad por sí solo. Esa confusión es tan común que terminó generando un estándar aparte, OpenID Connect, construido justamente encima de OAuth para resolver el problema de “quién es este usuario” que OAuth nunca prometió resolver.

OAuth 2.0 se formalizó en el RFC 6749 de octubre de 2012. Foto de Albert Stoynov en Unsplash

Por qué importa el estándar de autorización abierta

Antes de este estándar, la única forma de que una aplicación de terceros usara tu cuenta de otro servicio era pedirte la contraseña directamente. Ese patrón obligaba al usuario a confiar su credencial completa en una app que podía guardarla, filtrarla o abusar de ella sin ningún límite de alcance.

El protocolo de autorización resuelve ese problema separando dos cosas que antes iban juntas: quién sos y qué puede hacer una aplicación en tu nombre. Una app de terceros recibe un token con permisos acotados, nunca la contraseña, y ese token se puede revocar en cualquier momento sin tener que cambiar la clave de acceso.

Esa separación habilitó el ecosistema de integraciones que hoy damos por hecho. Cuando conectás Google Calendar con una app de productividad, o autorizás a un bot de Slack a leer un canal, el usuario decide exactamente qué scope otorga (solo lectura, solo un calendario, sin acceso a contactos) y la aplicación nunca almacena la contraseña real.

También resolvió un problema de escala para las plataformas grandes. Con tokens de vida corta y revocables, un proveedor como GitHub puede ofrecer miles de OAuth Apps de terceros sin que una filtración en una de ellas comprometa la cuenta completa del usuario en las demás integraciones.

Cómo funciona el flujo de autorización delegada

El estándar define cuatro participantes que interactúan en cada intercambio. El resource owner es el usuario que posee los datos. El client es la aplicación que quiere acceder a esos datos en su nombre. El authorization server verifica la identidad del usuario y emite los tokens. El resource server es la API que finalmente entrega el dato, validando el token antes de responder.

La siguiente figura resume cómo se relacionan estos cuatro roles:

flowchart TD
    U["Usuario (resource owner)"] --> AS["Servidor de autorizacion"]
    AS -->|"emite codigo"| C["Aplicacion cliente"]
    C -->|"intercambia codigo"| AS
    AS -->|"emite access token"| C
    C -->|"usa token"| RS["Servidor de recursos (API)"]
    RS -->|"responde datos"| C

El RFC 6749 define varios “grant types”, cada uno pensado para un tipo de aplicación distinto. El más usado hoy es el authorization code grant, diseñado para aplicaciones que pueden mantener un secreto en el servidor, o que usan PKCE si no pueden. El client credentials grant sirve para comunicación servidor a servidor sin usuario de por medio. El device authorization grant, definido después en el RFC 8628, resuelve el caso de una smart TV o una consola sin teclado cómodo: el dispositivo muestra un código corto y el usuario lo ingresa desde su teléfono.

⚠️ Ojo: el flujo implícito (response_type=token) devolvía el access token directamente en la URL del navegador. Quedaba expuesto en el historial y en los logs del servidor, así que la revisión actual del estándar lo desaconseja para proyectos nuevos en favor del authorization code grant con PKCE.

En el flujo con código, la secuencia es siempre la misma. La aplicación redirige al usuario al servidor de autorización con la lista de scopes solicitados. El usuario aprueba o rechaza el acceso desde una pantalla que controla el propio proveedor, nunca la aplicación cliente. Si aprueba, el servidor redirige de vuelta con un authorization code de un solo uso, que la aplicación cambia por un access token llamando directamente al servidor, sin que el navegador intervenga en ese paso.

sequenceDiagram
    participant U as Usuario
    participant C as Aplicacion
    participant AS as Servidor de autorizacion
    participant RS as Servidor de recursos
    C->>U: redirige a pantalla de login con code_challenge
    U->>AS: aprueba el acceso
    AS-->>C: redirige con authorization code
    C->>AS: intercambia code + code_verifier por token
    AS-->>C: responde con access token
    C->>RS: solicita datos con el token
    RS-->>C: responde con el recurso
    Note over C,AS: el code_verifier evita que un atacante use un code interceptado

El access token resultante suele tener formato opaco o JWT, y vive poco tiempo: minutos u horas. Junto con él, el servidor suele entregar un refresh token de vida más larga, que la aplicación cambia por un access token nuevo sin que el usuario vuelva a aprobar nada, hasta que ese refresh token también expire o sea revocado.

Ejemplos prácticos: cómo empezar con OAuth2

Para ver el flujo completo en acción alcanza con un navegador, curl y una cuenta de GitHub. GitHub expone un flujo de authorization code estándar que sirve como ejemplo real de cómo funciona cualquier integración de OAuth2 en producción.

Antes de escribir un solo comando hay que registrar una OAuth App en github.com/settings/developers. Ese registro entrega un client_id público y un client_secret privado, y pide declarar una redirect_uri (para este ejemplo, http://localhost:3000/callback).

Paso 1: construir la URL de autorización

https://github.com/login/oauth/authorize?client_id=Iv1.8a61f9b3a7aba766&redirect_uri=http://localhost:3000/callback&scope=read:user

Al abrir esta URL en el navegador, GitHub muestra la pantalla de aprobación. Si el usuario acepta, GitHub redirige a http://localhost:3000/callback?code=1a2b3c4d5e6f7g8h: ese code es el authorization code de un solo uso.

Paso 2: intercambiar el código por un token

curl -X POST https://github.com/login/oauth/access_token \
  -H "Accept: application/json" \
  -d client_id=Iv1.8a61f9b3a7aba766 \
  -d client_secret=tu_client_secret \
  -d code=1a2b3c4d5e6f7g8h

Salida esperada:

{"access_token":"gho_16C7e42F292c6912E7710c838347Ae178B4a","token_type":"bearer","scope":"read:user"}

Paso 3: llamar a la API con el token

curl -H "Authorization: Bearer gho_16C7e42F292c6912E7710c838347Ae178B4a" https://api.github.com/user

Salida esperada (simplificada):

{"login":"octocat","id":1,"name":"The Octocat"}

Paso 4: verificar el scope otorgado

Para confirmar qué permisos quedaron realmente autorizados en ese token, hay que mirar las cabeceras de la respuesta, no solo el cuerpo:

curl -I -H "Authorization: Bearer gho_16C7e42F292c6912E7710c838347Ae178B4a" https://api.github.com/user

La cabecera X-OAuth-Scopes: read:user en la respuesta confirma que el token tiene exactamente el scope solicitado, ni más ni menos.

Los tokens emitidos por GitHub para OAuth Apps llevan el prefijo gho_.

Casos de uso reales

El caso más visible para cualquier usuario es el botón “Continuar con Google” o “Continuar con GitHub” que aparece en miles de productos. Ese botón casi siempre combina el protocolo de autorización con OpenID Connect: el primero le da a la aplicación acceso a datos puntuales (el email, el perfil), el segundo confirma la identidad de quien inició sesión.

Las integraciones de terceros en redes sociales son otro ejemplo cotidiano. Una app que programa publicaciones en X, o un bot que lee mensajes en un canal de Slack, recibe un token con scopes específicos (publicar, leer un canal) y nunca ve la contraseña de la cuenta.

En pagos, Stripe Connect usa una variante del mismo esquema para que una plataforma marketplace reciba autorización de cada vendedor para procesar sus cobros, sin que el vendedor comparta sus credenciales bancarias con el marketplace. En dispositivos sin teclado cómodo, como una smart TV, servicios como YouTube usan el device authorization grant: el televisor muestra un código corto, el usuario lo escribe desde el teléfono y el token termina llegando al dispositivo sin que este haya tenido nunca acceso directo al formulario de login.

Errores comunes y buenas prácticas

  • Confundir autorización con autenticación: usar el access token para decidir “quién es” el usuario deja al desarrollador interpretando un token como prueba de identidad, algo que el estándar nunca garantizó.
  • Omitir el parámetro state: sin un valor aleatorio verificado al volver del servidor de autorización, la aplicación queda expuesta a ataques CSRF que fuerzan al usuario a autorizar una cuenta que no es la suya.
  • No implementar PKCE en clientes públicos: una SPA o una app móvil no puede guardar un client_secret real, así que sin code_verifier y code_challenge un authorization code interceptado alcanza para robar el token completo.
  • Guardar tokens en localStorage: un token accesible desde JavaScript queda expuesto a cualquier XSS en la página; las cookies httpOnly y secure reducen esa superficie de ataque.
  • Pedir scopes de más: solicitar acceso total cuando la aplicación solo necesita leer un dato puntual hace que, ante una brecha, el daño sea mayor, y además reduce la tasa de aprobación de los usuarios.
💡 Tip: si tu aplicación es una SPA o una app móvil, usá siempre PKCE. Sin él, el authorization code interceptado alcanza para robar el access token sin necesitar el client_secret.

Comparativa: OAuth2 frente a otros estándares de autorización

OpciónCuándo usarlaVentajaLimitación
OAuth 2.0 (code + PKCE)Apps web o móviles que acceden a APIs de tercerosTokens de corta vida, revocables, scopes granularesNo autentica identidad por sí solo
OpenID ConnectLogin o “Continuar con X”Añade una capa de identidad (ID token) sobre OAuth2Depende de la implementación de OAuth2 del proveedor
API KeysAPIs internas o integraciones servidor a servidor simplesSimplicidad, sin flujo de redirecciónSin expiración ni scopes granulares; si se filtra, acceso total
SAMLSSO empresarial tradicionalMaduro y estándar en entornos corporativosPesado para APIs REST o apps móviles modernas

Profundizando: PKCE y el interior del flujo de OAuth2

PKCE (Proof Key for Code Exchange, RFC 7636) resuelve un problema específico de los clientes públicos: una SPA o una app móvil no puede guardar un client_secret sin exponerlo en el código. Sin ese secreto, cualquiera que intercepte el authorization code (por ejemplo, vía un deep link mal configurado) podría cambiarlo por un token.

La solución es generar, en el propio cliente, una cadena aleatoria llamada code_verifier. Antes de redirigir al usuario, la aplicación calcula code_challenge = BASE64URL(SHA256(code_verifier)) y lo envía junto con el pedido de autorización. Al momento de cambiar el código por el token, la aplicación envía el code_verifier original; el servidor recalcula el hash y lo compara contra el code_challenge que guardó al inicio. Si no coinciden, rechaza el intercambio, aunque el atacante tenga el code.

Otro detalle que separa implementaciones maduras de las básicas es si el access token es opaco o un JWT firmado. Un token opaco obliga al resource server a consultar al authorization server en cada request vía el endpoint de introspección (RFC 7662). Un JWT, en cambio, permite validar la firma localmente sin esa llamada extra, a costa de no poder revocarlo instantáneamente sin una lista de revocación aparte.

stateDiagram-v2
    [*] --> Emitido
    Emitido --> Activo
    Activo --> Expirado: pasan los minutos de vida util
    Expirado --> Activo: se usa el refresh token
    Activo --> Revocado: el usuario retira el acceso
    Revocado --> [*]
    Expirado --> [*]: el refresh token tambien expiro

Un desarrollo más reciente del propio ecosistema es DPoP (RFC 9449), que ata el access token a una clave criptográfica que solo tiene el cliente legítimo. Así, robar el token solo (sin esa clave) deja de ser suficiente para usarlo en otro lugar, algo que los tokens bearer tradicionales nunca podían evitar.

📖 Resumen en Telegram: Ver resumen

Tu próximo paso: registrá una OAuth App gratis en github.com/settings/developers y repetí los cuatro comandos curl de este artículo contra tu propia cuenta para ver en vivo el intercambio de código por token.

📬 Recibí lo nuevo en tu email

Te avisamos de artículos grandes (1-2 por mes).

Preguntas frecuentes

¿OAuth 2.0 reemplaza las contraseñas por completo?

No. El usuario sigue autenticándose con contraseña (o passkey, o 2FA) directamente en el servidor de autorización. Lo que OAuth evita es que esa contraseña se comparta con la aplicación de terceros.

¿Qué diferencia a OAuth2 de OpenID Connect?

OAuth2 autoriza acceso a datos o acciones; OpenID Connect se construye encima para confirmar identidad, agregando un ID token firmado que certifica quién inició sesión.

¿Sigue siendo seguro el flujo implícito del protocolo de autorización abierta?

No se recomienda para proyectos nuevos. Devuelve el token directamente en la URL del navegador, lo que lo expone en historial y logs; el authorization code grant con PKCE lo reemplaza en prácticamente todos los casos.

¿Qué es PKCE y por qué lo necesita el flujo de autorización delegada?

Es una extensión (RFC 7636) que protege a los clientes públicos, como SPAs y apps móviles, que no pueden guardar un client_secret sin exponerlo en el código fuente.

¿Cuánto dura un access token en OAuth2?

Varía por proveedor, pero suele ir de minutos a pocas horas. La vida corta es intencional: limita el daño si el token se filtra.

¿Qué pasa si se filtra un refresh token de OAuth2?

Un atacante puede generar access tokens nuevos indefinidamente hasta que el usuario o el proveedor lo revoquen manualmente, por eso los refresh tokens deben guardarse con al menos el mismo cuidado que una contraseña.

Referencias

  • RFC 6749: especificación oficial del IETF para OAuth 2.0.
  • RFC 7636: define PKCE, la extensión para clientes públicos.
  • oauth.net/2: sitio de referencia de la comunidad OAuth, mantenido por uno de los coautores del estándar.
  • GitHub Docs: guía oficial para implementar el flujo de autorización usado en los ejemplos de este artículo.
  • RFC 8628: define el device authorization grant usado en TVs y consolas.

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Zaqy Al Fattah en Unsplash

¿Te sirvió? ¿Te dio otro error? Contalo abajo: las preguntas se responden y le sirven al siguiente que llegue.

Dejar un comentario

Clara Vásquez

Analista de ciberseguridad enfocada en vulnerabilidades críticas, zero-days y amenazas emergentes. Cubre CVEs de alto impacto, análisis de malware, incidentes de ransomware y tendencias de seguridad para LATAM.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Podés incluir código entre <code>…</code> o, para varias líneas, <pre><code>…</code></pre>.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.