OAuth 2.0: Principios de la autenticación de terceros
Al finalizar este tema
Comprenderás el problema que resuelve OAuth 2.0, el flujo completo del Authorization Code Flow y las funciones del token de acceso y del token de actualización.
¿Por qué no se solicita la contraseña?
Al hacer clic en los botones "Iniciar sesión con Google" o "Iniciar sesión con Kakao", no ingresas tu contraseña en nuestro servicio. En cambio, se te redirige a la pantalla de Google para iniciar sesión allí y luego regresas.
¿Por qué se diseñó de esta manera tan compleja? La respuesta es simple: no debemos enviar la contraseña a servidores de terceros.
Si un servicio te pidiera que ingresaras tu correo electrónico y contraseña de Google, ese servicio podría almacenar tu contraseña. Si se produce una filtración, tu cuenta de Google podría verse comprometida por completo. OAuth resuelve este problema al proporcionar un "permiso" en lugar de la contraseña.
Los cuatro actores
En OAuth, existen cuatro roles:
| Rol | Significado | Ejemplo |
|---|---|---|
| Propietario del recurso | Usuario (propietario de los datos) | Yo |
| Cliente | Nuestro servicio | Nuestra aplicación web |
| Servidor de autorización | Servidor que se encarga de la autenticación | Servidor de autenticación de Google |
| Servidor de recursos | Servidor donde se encuentran los datos del usuario | API de perfil de Google |
Los nombres no son del todo intuitivos. Ten en cuenta que "Cliente" no se refiere al usuario, sino a nuestro servidor. Desde la perspectiva de OAuth, nuestro servicio actúa como el solicitante que pide datos a Google, por lo que se denomina Cliente.
Flujo de código de autorización
Es el flujo más utilizado. Veamos los pasos:
1. El usuario hace clic en "Iniciar sesión con Google"
2. Nuestro servidor redirige al servidor de autenticación de Google
→ La URL incluye client_id, redirect_uri, scope
3. El usuario inicia sesión en Google y hace clic en "Permitir a esta app"
4. Google transmite el "código de autorización (code)" a redirect_uri
5. Nuestro servidor solicita a Google con el código de autorización + client_secret
6. Google emite un Access Token
7. Nuestro servidor solicita la información del usuario con el Access TokenLa clave está en que se realiza un intercambio en dos pasos. Primero se obtiene el código de autorización (de un solo uso) y, a continuación, se utiliza ese código para obtener el token real. ¿Por qué no se entrega el token directamente en un solo paso?
En el paso 4, el código de autorización se transmite como parámetro en la URL. Las URL se guardan en el historial del navegador y se registran en los logs. Si el token estuviera incluido allí, cualquiera podría verlo. Dado que el código de autorización es de un solo uso y expira en un breve período de tiempo, incluso si se viera comprometido, el daño sería limitado.
En el paso 5, el intercambio por el token real se realiza mediante una comunicación entre servidores (canal seguro). Se incluye client_secret, que nunca se expone al navegador.
Token de acceso y token de actualización
// Estructura del token que responde Google (ejemplo)
{
"access_token": "ya29.a0AfH6SM...",
"expires_in": 3600, // 1 hora
"refresh_token": "1//0eXyz...",
"token_type": "Bearer",
"scope": "email profile"
}| Token | Vida útil | Uso |
|---|---|---|
| Access Token | Corta (generalmente 1 hora) | Se utiliza para las llamadas a la API |
| Refresh Token | Larga (semanas a meses) | Para renovar el Access Token |
Cuando el Access Token expira, se obtiene un nuevo Access Token utilizando el Refresh Token. Esto evita tener que pedirle al usuario que inicie sesión de nuevo cada vez.
¿Por qué no se crean Access Tokens con una vida útil más larga? El objetivo es minimizar el período de riesgo en caso de que el token se vea comprometido. Si un token válido por 1 hora se ve comprometido, el riesgo persiste solo durante esa hora; si uno válido por 1 año se ve comprometido, el riesgo se extiende durante todo ese año.
scope — Alcance de los permisos
https://accounts.google.com/o/oauth2/v2/auth?
client_id=OUR_CLIENT_ID&
redirect_uri=http://localhost:3000/callback&
scope=email+profile&
response_type=codescope define el alcance del acceso. Si se establece email profile, solo se puede acceder al correo electrónico y a la foto de perfil; no se pueden ver los archivos de Google Drive.
El alcance se refiere a la información que se muestra en la pantalla que ve el usuario al hacer clic en "Permitir que esta aplicación acceda", indicando, por ejemplo, "Esta aplicación verificará tu dirección de correo electrónico".
Principio de mínimo privilegio: solicita solo lo necesario. Solicitar "todos los permisos" puede asustar al usuario y hacer que rechace la solicitud.
Implementación en nuestro servicio
Aspectos clave a tener en cuenta durante la implementación:
- Registro del proveedor: Registra la aplicación en las consolas de desarrolladores de Google/Kakao y obtén
client_idyclient_secret. - Configuración de
redirect_uri: Registra la URL de retorno donde se recibirá el código de autorización; las redirecciones a URL no registradas serán rechazadas. - Validación del valor
state: Incluye una cadena aleatoria en la solicitud para prevenir ataques CSRF y verifica su coincidencia en la respuesta.
// Manejo de callback en Express (concepto)
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// 1. Validación del estado (prevención CSRF)
if (state !== req.session.oauthState) {
return res.status(403).send('Invalid state');
}
// 2. Intercambio de código de autorización por token (servidor → Google, canal trasero)
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: new URLSearchParams({
code,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code',
}),
});
const { access_token } = await tokenRes.json();
// 3. Solicitud de información del usuario con el Token de Acceso
const userRes = await fetch(
'https://www.googleapis.com/oauth2/v2/userinfo',
{ headers: { Authorization: `Bearer ${access_token}` } }
);
const user = await userRes.json();
// 4. Guardar usuario en la sesión
req.session.user = user;
res.redirect('/');
});Esencial
OAuth 2.0 es un protocolo que otorga permisos mediante tokens en lugar de contraseñas. El flujo de autorización implica un intercambio en dos pasos: código de autorización (de un solo uso) → token de acceso (de corta duración) → llamada a la API. Los tokens de acceso tienen una duración limitada y se renuevan con un token de actualización, lo que minimiza el impacto en caso de filtración.
→ En el siguiente tema, implementaremos Passport.js + Google OAuth.