This document captures design, considerations, and (eventually) decisions regarding the mitigation of CSRF attacks in the context of mod-login-saml.  Here are some helpful links providing background information on CSRF attacks and SAML in general:


In order to prevent CSRF attacks, we need some way to check if the user making the call to POST /saml/login is the same user making the call to POST /saml/callback.  At a high level, we're looking at something like this:

  1. user clicks "sign in via sso", triggering a call to POST /saml/login. 
  2. mod-saml-login generates a csrfToken, sets a cookie with that value.  Also includes the csrfToken in the RelayState param returned along with the SAMLRequest
  3. stripes either redirects or POSTS to the IdP - SAMLRequest + RelayState (depending on which binding is being used)
  4. the IdP challenges the user for credentials and generates an auto-submitting form that POSTS to /saml/callback with the SAMLResponse and original RelayState (and the csrfToken cookie set for folio's domain)
  5. mod-login-saml compares the csrfToken from RelayState to the value in the csrfToken cookie, if they match we proceed, otherwise it suggests that this could be a CSRF attempt and we reject

Here's where things break:




Frontend Redirect/Callback URL

Once the user authenticates with the IdP, the IdP generages an auto-submitting form that posts to a callback URL.  Currently this is POST /saml/callback handled by mod-login-saml.  One idea was to use a stripes URL instead and essentially proxy the callback to the backend.  The idea here is that it simplifies the CORS handling for the FOLIO backend, which would only need to whitelist the stripes origin, not the IdP origin as well.  My opinion is that this isn't really worth it, but I thought it should be mentioned here anyway.



Other Considerations:


Other Considerations