Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

CSRF fails after the server restart #832

emirotin opened this Issue Jun 28, 2013 · 13 comments


None yet
3 participants

Using express 3.2.6

Here's my relevant code

csrf_token = (req, res, next) ->
    res.locals.csrf_token = req.session._csrf

    .use('/v1', express.csrf())

Then in my view I have

    div(style="display: none")
        input#csrf-token(type="hidden", value="#{csrf_token}")

And finally I pick this value before every AJAX request.

Appears that after the server restart upon opening the page for the 1st time csrf_token is undefined that makes all my requests fail until I reload the page.


jonathanong commented Jul 1, 2013

if the route is anything but /v1 then req.session._csrf is going to be undefined

emirotin commented Jul 1, 2013

@jonathanong obviously, but the route is /v1/service/inv-view and as I explained the issue only happens the first time I load the page and doesn't happen after reload


jonathanong commented Jul 1, 2013

'/v1' !== '/v1/service/inv-view'. you want .use('/v1*', express.csrf())

emirotin commented Jul 1, 2013

I don't think you're right.

Say for example you wanted to prefix all static files with "/static", you could use the "mounting" feature to support this. Mounted middleware functions are not invoked unless the req.url contains this prefix, at which point it is stripped when the function is invoked. This affects this function only, subsequent middleware will see req.url with "/static" included unless they are mounted as well.

I also have different middleware mounted to prefixes in the same way and they work OK


jonathanong commented Jul 1, 2013

errr you're right. was thinking about routing


jonathanong commented Jul 1, 2013

what happens if you just .use(express.csrf())?

emirotin commented Jul 1, 2013

The same
(and I need mounting cause I also get POSTs from Facebook who cannot pass the token)


tj commented Jul 5, 2013

you're using the in-memory session store, you'll want to pass something like connect-redis to .session({ store: .. })

@tj tj closed this Jul 5, 2013

emirotin commented Jul 6, 2013

But why isn't in-memory store working?
I didin't find in docs that I must use some persistent storage


tj commented Jul 8, 2013

it does work, but when the process goes down all the sessions go with it, the memory store is only really useful for tiny "toy" sites and development

emirotin commented Jul 8, 2013

But it doesn't actually

I restart the server
I request the page
I expect the server to generate the token
() I put this token to res.locals and out put it to the page
Then I pick it from the page and put inside of the AJAX request payload
And I see that when the page loads for the first time the token from (
) is undefined

It is obvious that in-memory store is erased when the server restarts, of course. But I don't complain about my old session lost.
I tell you that the new token does not reach the page when it loads for the first time.


tj commented Jul 9, 2013

oh ok I see, hmm, can you reproduce with a small stand-alone app I can check out? or better yet a test for this repo

OK, I have it reproducible https://www.dropbox.com/s/n6vq4xjpjznfhgx/token-error.zip
And I assume I also have an explanation

I only want CSRF to be checked on POSTS to specific prefix (like '/api'), so I mount it to that prefix.
Which means the middleware itself isn't called for other requests

Now what happens:
GET '/' -> middleware not called, session._csrf not set, page renders with undefined inside of input
pick _csrf from the input (undefined)
POST '/api/time' -> middleware is called, it sets session._csrf to a newly generated value, then picks _csrf == undefined from my post body and fails

Now when I reload the page the token is already in session._csrf and thus reaches the page

Solution? Creating 2 middleware (initCsrf -> mount for every request, checkCsrf -> mount for particular point).
See https://www.dropbox.com/s/tmlamdb5w51cpac/token-error2.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment