Reputation: 9890
I have a ring
webapp that uses noir.session
as follows:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults site-defaults))) ; both from ring.middleware.defaults
However, it seems like session variables are lost between the requests. The server keeps sending a Set-Cookie
header even though the client provides the Cookie
header.
Using trial and error, I found out that when I disable ring's anti-forgery wrapper as follows, the same session lives across requests:
(def app (-> app-routes
(session/wrap-noir-session)
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))))
but of course I don't want that. Why is this, and how can I fix my problem without risking CSRF attacks?
Upvotes: 0
Views: 123
Reputation: 9890
Browsing the source code of all involved middleware, I found out that lib-noir's wrap-noir-session
re-implements parts of ring's wrap-session
. That lead me to the following experiment:
(def app (-> app-routes
(session/wrap-noir-session {:store (memory-store)})
(wrap-defaults (assoc site-defaults :session false))))
Here as well, sessions live across requests.
Here's the culprit: wrap-defaults
already applies wrap-session
, so when the wrap-noir-session
handler is listed as well, wrap-session
is actually invoked twice.
The final solution couldn't be simpler: Use wrap-noir-session*
instead. According to the docs, it "expects that wrap-session has already been used." It seems that the contrary is true for wrap-noir-session
.
(def app (-> app-routes
(session/wrap-noir-session*)
(wrap-defaults site-defaults)))
Hopefully, this will save you some time.
Upvotes: 2