David Rio

Understanding CSRF

The problem

Recently I have been working on integrating SAML SSO within Caddy. I realized that some security measures are necessary to avoid CSRF(cross-site request forgery) attacks. When the SAML flow finishes, the client ends up with a JWT cookie. That cookie contains the necessary bits for the SP and IDP to establish a session. Once that cookie is in place the user is authenticated and can use the service provided by the IDP without having to enter her credentials. Once the cookies expires (or the user logouts), the SAML flow starts over.

Typically users will not logout and they continue navigating the web. Depending on the SP configuration, third-party sites can make requests to the SP without the user noticing. Those requests can perform unauthorized actions against the SP.

Notice that this attack vector will also happen in other types of authentication methods, for example basic auth.

Possible solutions

There are, as far as I know, a couple of things we can do reduce the risk.

SameSite attribute in the JWT cookie

When creating the session cookie, we can set the samesite attribute to lax or strict. If we use lax:

"Cookies are not sent on normal cross-site sub-requests (for example to load images or frames into a third party site), but are sent when a user is navigating to the origin site (i.e., when following a link)."

If the cookie is not available when making POST, PUT and DELETE http requests the server will not execute those.

That is fine for when we implement sessions with things like JWT tokens (what we use in SAML), but this won't help us when we do basic authentication. That leads us to ...

Token-based mitigation: double-submit cookie pattern

What we do here is to generate a random token in the backend and add it as a hidden field the forms we use in our site. When we submit the forms, the backend's endpoint is protected with middleware that expects the token in the payload. The middleware continues only if that token is available. Here is one implementation for golang.