Closed bradtaniguchi closed 3 years ago
There is no issue using the double submit pattern with angular. The issue in your code above is that you are trying to set two different values to the same cookie name: the cookie.key
configuration is (in the words of the docs here) "the name of the cookie to use to store the token secret". You are using the name XSRF-TOKEN
for this cookie, which is probably confusing, as this specifies the token secret, not the token itself. Then later in your code, you use res.cookie
to set a different value to that same cookie name, namely you are saving the csrf token to that value.
The solution is to not use the same cookie name, as outlined in our docs. I understand that if you are following tutorials from other tutorials and blogs they create a lot of confusion, but it's unfortunate we cannot control those.
But there is no issue using double-submit cookie with Angular if you want to use that pattern -- but you can only store a single value in a given cookie per web browser restrictions. Don't choose to store two different values in the same cookie name :)
Here would be a "fixed" version of your config:
import csrf from 'csurf';
//.. where middlewares are defined on my server-side
csrf({
cookie: {
// according to the docs, this implements the double cookie pattern
// so this will be the name of the cookie to store the token secret
key: 'XSRF-SECRET'
}
})(req, res, (err) => {
if (err) {
logger.debug(err); // above error appears here
// re-throw with my own error to handle it elsewhere
throw new CsrfError();
}
next();
})
//.. elsewhere in a GET controller/route I send the XSRF-TOKEN csrf "expects":
return res.cookie('XSRF-TOKEN', req.csrfToken()).send(/*stuff*/);
Hello, I've spent a significant portion of my life dealing with the following error:
After
smashing my head against this errordebugging I've found that I was making a mistake between the different approaches to protecting against csrf attacks. Namely mixing this librarie's double submit cookie pattern and my client framework (Angular) default's approach cookie-to-header token pattern, which results in the above error.There can be multitude of reasons the above error appears, but the nature to which it occurs seems like it should work at a glance, as technically each side is doing things correctly.
I might not be the best networking or security guy, but I was able to figure this out and feel like it was much more of a pain simply due to me not paying attention to what I think are a few glossed over but critical details.
The Wrong configuration
My server-side was configured with the following:
I was using a nestjs setup, so my middlewares where defined slightly different than a stock express app, but I digress. I just want to provide as much context to this as possible. For an express app you would probably have something like:
From here on out I'll stick to express examples, as such a setup would apply to more people. There might be slight syntax issues though.
On the client-side I was using Angular, which as the docs state:
Without reading any further, one might assume this means Angular will automatically grab the XSRF-TOKEN and magic security stuff will automatically happen, except that isn't what happens. Once you make POST requests,
csurf
gives the above error, even though it would appear at a glance everything is configured correctly. Both sides are configured correctly, except they are configured differently at this point, which results in the above error.If one were to continue reading the Angular docs mentioned above, they would continue:
Which will be set and being sent to the server-side where it promptly explodes with the above error. Even though at a glance, the header:
X-XSRF-TOKEN
and the cookie:XSRF-TOKEN
will be the same. Which is actually wrong, as csurf doesn't expect it due to the way its configured it expects double cookies.The correct configuration:
The correct configuration for this situation is actually set
csrf
to be the following:which by default will follow the cookie-to-header token pattern, which is what Angular does. Later in a route you still set the cookie as already mentioned:
And bam POST requests now go thru as expected.
Soooo whats the point of all that?
Can we update the docs to point out/warn against using the double submit cookie pattern for SPA applications like Angular? Or mixing the two approaches?
If anything I hope this issue helps document such a case/setup and the potential pitfalls of setting stuff up as such.
ref: