Fork me on GitHub
#reagent
<
2019-01-16
>
Jenny Kwan05:01:08

Hi everyone. Having trouble figuring out how to get ring-anti-forgery to work on client side JS forms. It seems like the client side JS process doesn't have access to the server vars, so I can't simply add a hidden field with *anti-forgery-token* as the value. Given that index.html is retrieved only once, I assume this isn't the CSRF token that is used for the lifetime of the browser process. I can't be the only one facing this; but I can't find anything. Does every request to the server have to also update the client-side CSRF token? That seems crazy...

lilactown05:01:20

@me1238 you’ll want to send the anti forgery token in the initial index.html

Jenny Kwan05:01:21

Does ring-anti-forgery do session-level CSRF?

Jenny Kwan05:01:01

I haven't gone into the code, but its mention of "synchronizer pattern" implies (to me) request-level tokens.

Jenny Kwan05:01:49

Session-level it is. Seems insecure to me, but I don't do infosec.

Jenny Kwan05:01:19

So I get it from index.html, presumably in the header, and use that to seed the initial re-frame state (using re-frame in my app).

Jenny Kwan05:01:57

The only issue is that I have to treat every GET of index.html as a new session. But to Ring, there is no session, unless each HTTP request from reagent/re-frame sets the session ID in the header, perhaps by cookie. So these are anon GETs. How do I ensure Ring forces a new CSRF token on the server side with each index.html GET?

Jenny Kwan06:01:48

If a cookie is never set, each HTTP request belongs to a new session.

Jenny Kwan06:01:19

It raises the question of how to make reagent/re-frame set the cookie on login, but that's later.

orestis11:01:53

Wow @me1238 that answers my question as well - I always thought CSRF tokens were request level. Thanks!

Jenny Kwan18:01:36

@orestis They can be. If using Ring, just swap out the strategy. But out of the box they're not.

Jenny Kwan18:01:04

It seems like the best way is to - within re-frame's main before the main-panel render - do a GET request to an /api/init route handler, which will include the token in the response header. https://github.com/Day8/re-frame/wiki/Bootstrap-An-Application This has the added benefit of supporting session resumption, which is typically what one would want.

🙂 5
Jenny Kwan18:01:29

It looks like Chestnut generates a template for core.cljs with a render function that does a dispatch-sync with the :initialize-db event, which would be where all this goes.

Jenny Kwan18:01:36

Sorry, this is getting really re-frame specific. Will move.