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?
Browsing the source code of all involved middleware, I found out that lib-noir's
wrap-noir-sessionre-implements parts of ring'swrap-session. That lead me to the following experiment:Here as well, sessions live across requests.
Here's the culprit:
wrap-defaultsalready applieswrap-session, so when thewrap-noir-sessionhandler is listed as well,wrap-sessionis 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 forwrap-noir-session.Hopefully, this will save you some time.