ecosystem-wikicómo extender los templates sin romper sus convenciones
‹ todo el contenido

El ida y vuelta del login

dev-identity-server
último cambio 2026-09-25

El recorrido completo cruza dos servicios y tres dominios, y entenderlo entero es lo que permite depurarlo cuando falla a mitad.

1. navegador → panel protegido        (no tiene sesión)
2. panel     → /auth/google           con ?redirect_uri=…
3. identity  → Google                 con state, y dos cookies guardadas
4. Google    → /auth/google/callback  con ?code&state
5. identity  → valida, crea sesión y redirige al panel con ?token=
6. panel     → verifica el token y pone su propia cookie
7. navegador → panel                  (ya con sesión)

1-2 · Nadie tiene destino por defecto

El panel manda al usuario a /auth/google y está obligado a decir a dónde volver:

const redirectUri = req.query.redirect_uri as string | undefined;
if (!redirectUri) return res.status(400).json({ error: "redirect_uri is required" });
if (!config.allowedRedirectUris.includes(redirectUri))
  return res.status(400).json({ error: "redirect_uri is not allowed" });

No hay frontend por defecto al que caer: si el redirect_uri falta o no está en la allowlist, el flujo muere aquí con un 400. Por qué se valida así, en las dos defensas.

3 · Dos cookies de diez minutos

Antes de mandar al usuario a Google se guardan dos cookies, ambas httpOnly y con diez minutos de vida: oauth_state (el testigo anti-CSRF) y oauth_redirect (a dónde volver). Son lo único que ata la vuelta de Google con el navegador que empezó.

4-5 · La vuelta

En el callback se comprueban las dos cosas —el state coincide y el destino sigue siendo válido— y las cookies se borran antes de decidir nada, hayan salido bien o mal. Después se canjea el code con Google, se verifica el id_token, y se crea o recupera el usuario.

Aquí se emite la sesión propia: un access token JWT de 15 minutos firmado con IDENTITY_JWT_SECRET, y un refresh token opaco de 40 bytes que se guarda hasheado con SHA-256 y viaja en una cookie httpOnly de 7 días.

5 · El token viaja en la URL, y por qué

Es la parte que más llama la atención:

target.searchParams.set("token", accessToken);
res.redirect(target.toString());

El motivo está comentado en el código: el consumidor está en otro dominio y no puede leer la cookie httpOnly de este servidor. La única forma de entregarle la sesión es adjuntando el access token a la propia redirección.

Por eso el access token dura 15 minutos y por eso se espera que el consumidor redirija otra vez inmediatamente después de guardarlo: así el token no se queda en el historial del navegador.

6 · La parte que ocurre en el otro repo

El consumidor no confía en el token por venir de donde viene: lo verifica otra vez antes de guardarlo, y lo cambia por una cookie propia. Eso es proteger un panel.

Dónde falla, y qué significa

Síntoma Dónde Causa habitual
400 redirect_uri is not allowed paso 2 falta en ALLOWED_REDIRECT_URIS, o no coincide exacto
400 Invalid or missing OAuth state paso 4 la cookie caducó (más de 10 min), o el navegador no la devolvió
400 Missing or expired redirect_uri paso 4 misma causa, la otra cookie
500 Authentication failed paso 4 falló el canje con Google: credenciales o GOOGLE_REDIRECT_URI mal
Entra y al rato se cae la sesión paso 7 normal si el servicio se reinició — las sesiones viven en memoria

Ese último es el que más despista, y no es un fallo: ver qué es, y qué no es.