CSRF Protection para Hipsters
Disclaimer: No soy experto en seguridad, estas son notas sobre mi búsqueda.
Estaba haciendo una PWA chiquita, sin romper nada, hasta que me tocó llegar a la parte de la autenticación.
Para este caso de uso no puedo usar un servicio como Auth0 y armar un buen esquema con JWT que rotan bien es un bardo, preferí ir por los no tan hipsters y bien queridos token sessions con una cookie HTTP.
El problema llegó cuando le quise meter CSRF tokens para proteger a la app. Como quería servir el front desde una CDN no podía usar el esquema típico de meter el token en el HTML porque no hay un server atrás.
Lo que se me ocurrió fue crear un endpoint que me traiga un csrf token en una cookie al bootear la app. Ahí fue cuando me encontré lo siguiente en el artículo de understanding csrf recomendado por csurf, la librería más usada para CSRF protection en node.js:
Don't ever create a GET /csrf route in your app and especially don't enable CORS on it. Don't send CSRF tokens with API response bodies.
Con lo cual pensé que esta no era una opción viable.
Same-Site Lax cookies
Como el frontend de mi app corre en el mismo dominio (distinto subdominio) del backend y como el target son navegadores modernos (IE11 es moderno, ponele), podemos usar una feature que protege nuestras cookies de sesión. Seteando la cookie de sesión como SameSite=Lax en conjunto con HTTPOnly tenemos la seguridad de SameSite=Strict donde las credenciales no se transmiten entre distintos dominios salvo en requests GET, cosa que si entramos al sitio desde un link, la sesión se envíe y no perdamos el flujo del usuario autenticado.
En los artículos que leí se recomiendan los tokens de CSRF por compatibilidad con browsers no tan modernos y por ser future proof, ya que la protección pasa por la app y no por features del browser.
Tan mala es la idea del endpoint para obtener tokens?
Si bien el artículo que menciono no lo recomienda ni un poquito, encontré que frameworks como Laravel que usan esta estrategia y hay una conversación al respecto en el artículo que cité antes ¯_(ツ)_/¯.