CORS, CSRF y Cookies
CORS, CSRF y cookies
Section titled “CORS, CSRF y cookies”Cuando el navegador autentica con cookies, CORS, CSRF y cookies forman una sola superficie de seguridad.
Reglas:
CORS_CREDENTIALS=truesolo con allowlist exacta.- Nunca usar
*con credenciales. - Reflejar solo origenes permitidos.
- Enviar
Vary: Origincuando se refleja origen. - Permitir
X-CSRF-Tokenen preflight. OPTIONSno debe requerir auth, pero debe rechazar origen no permitido.Authorizationpuede seguir permitido para compatibilidad legacy/no navegador, pero el navegador no debe depender de el.
Pruebas CORS
Section titled “Pruebas CORS”| Caso | Request | Esperado |
|---|---|---|
| Origin permitido | OPTIONS /api/auth/login con Origin: https://app.<dominio> | 204, Access-Control-Allow-Origin exacto, credentials true. |
| Origin no permitido | OPTIONS /api/auth/login con Origin: https://evil.example | 403, sin credentials. |
| Sin Origin | GET /api/auth/session sin Origin | Pasa a app, sin reflejar wildcard. |
| Header CSRF | Preflight con Access-Control-Request-Headers: X-CSRF-Token | Header permitido. |
| Wildcard | Cualquier response autenticada por cookies | No debe aparecer Access-Control-Allow-Origin: * con credentials. |
Modelo implementado:
- Signed double-submit.
- Cookie CSRF no
HttpOnly. - Header
X-CSRF-Token. - Cookie y header deben coincidir.
- Firma HMAC con
CSRF_TOKEN_SECRET. - Binding
preauthosession. - Origin/Referer como defensa adicional.
Pruebas CSRF
Section titled “Pruebas CSRF”| Caso | Esperado |
|---|---|
| Sin header | 403 CSRF_FORBIDDEN, reason missing_header. |
| Header invalido | 403 con reason malformed, bad_signature, mismatch o equivalente. |
| Cookie ausente | 403 missing_cookie. |
| Cookie/header no coinciden | 403 mismatch. |
| Origin no permitido | 403 origin_not_allowed. |
| Token expirado | 403 expired. |
| Token valido | Request alcanza el controller o siguiente middleware. |
Cookies
Section titled “Cookies”Production-like:
AUTH_COOKIE_ACCESS_NAME=__Host-medsync_atAUTH_COOKIE_REFRESH_NAME=__Host-medsync_rtAUTH_CSRF_COOKIE_NAME=__Host-medsync_csrfAUTH_COOKIE_SECURE=trueAUTH_COOKIE_SAMESITE=laxAUTH_COOKIE_DOMAIN=AUTH_COOKIE_PATH=/AUTH_COOKIE_MAX_AGE_MODE=sessionValidaciones:
__Host-medsync_aty__Host-medsync_rt:HttpOnly=true.__Host-medsync_csrf:HttpOnly=false.- Todas:
Secure=true,SameSite=Lax,Path=/. - Ninguna
__Host-debe tenerDomain. - Logout expira las tres cookies.
Local HTTP
Section titled “Local HTTP”Solo para desarrollo:
AUTH_COOKIE_MODE=d2BROWSER_AUTH_TRANSPORT=cookieAUTH_COOKIE_ACCESS_NAME=medsync_at_devAUTH_COOKIE_REFRESH_NAME=medsync_rt_devAUTH_CSRF_COOKIE_NAME=medsync_csrf_devAUTH_COOKIE_SECURE=falseAUTH_COOKIE_SAMESITE=laxAUTH_COOKIE_DOMAIN=AUTH_COOKIE_PATH=/AUTH_COOKIE_MAX_AGE_MODE=sessionCSRF_ENABLED=trueCORS_CREDENTIALS=trueNo uses esta configuracion para staging ni produccion.
Sintomas comunes
Section titled “Sintomas comunes”| Sintoma | Causa probable | Revision |
|---|---|---|
| Login 403 | Falta CSRF o Origin no permitido. | /api/auth/csrf, header X-CSRF-Token, CSRF_ALLOWED_ORIGINS. |
| Browser no guarda cookies | Secure con HTTP local o SameSite/Domain incorrecto. | DevTools cookies y flags. |
| Frontend recibe 401 tras login | /api/auth/session no recibe access cookie. | withCredentials, CORS credentials, cookie domain/path. |
| Preflight falla | Header/metodo no permitido. | CORS_ALLOWED_HEADERS, CORS_ALLOWED_METHODS. |
| Cookie no se limpia en logout | Atributos de clear no coinciden. | Path/domain/samesite/secure iguales al set. |