Skip to content

Commit

Permalink
[#198] Add CSRF token header compatible with ring.middleware defaults…
Browse files Browse the repository at this point in the history
…, etc.

Thanks to @theasp for bringing attention to this
  • Loading branch information
ptaoussanis committed Feb 5, 2016
1 parent a318bb3 commit bd833d2
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 29 deletions.
5 changes: 3 additions & 2 deletions example-project/src/example/client.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@

(sente/ajax-lite "/login"
{:method :post
:params {:user-id (str user-id)
:csrf-token (:csrf-token @chsk-state)}}
:headers {:X-CSRF-Token (:csrf-token @chsk-state)}
:params {:user-id (str user-id)}}

(fn [ajax-resp]
(->output! "Ajax login response: %s" ajax-resp)
(let [login-successful? true ; Your logic here
Expand Down
17 changes: 6 additions & 11 deletions example-project/src/example/server.clj
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,12 @@
(route/not-found "<h1>Page not found</h1>"))

(def main-ring-handler
(let [ring-defaults-config
(assoc-in ring.middleware.defaults/site-defaults
[:security :anti-forgery]
{:read-token (fn [req] (-> req :params :csrf-token))})]

;; NB: Sente requires the Ring `wrap-params` + `wrap-keyword-params`
;; middleware to work. These are included with
;; `ring.middleware.defaults/wrap-defaults` - but you'll need to ensure
;; that they're included yourself if you're not using `wrap-defaults`.
(ring.middleware.defaults/wrap-defaults
ring-routes ring-defaults-config)))
"**NB**: Sente requires the Ring `wrap-params` + `wrap-keyword-params`
middleware to work. These are included with
`ring.middleware.defaults/wrap-defaults` - but you'll need to ensure
that they're included yourself if you're not using `wrap-defaults`."
(ring.middleware.defaults/wrap-defaults
ring-routes ring.middleware.defaults/site-defaults))

;;;; Sente event handlers

Expand Down
30 changes: 14 additions & 16 deletions src/taoensso/sente.cljx
Original file line number Diff line number Diff line change
Expand Up @@ -714,15 +714,7 @@
(if handshake? :handshake :non-handshake) clj)

(when handshake?
(let [[_ [?uid ?csrf-token ?handshake-data] :as handshake-ev] clj
;; Another idea? Not fond of how this places restrictions on the
;; form and content of ?handshake-data:
;; handshake-ev [:chsk/handshake
;; (merge
;; (have [:or nil? map?] ?handshake-data)
;; {:?uid ?uid
;; :?csrf-token ?csrf-token})]
]
(let [[_ [?uid ?csrf-token ?handshake-data] :as handshake-ev] clj]
(when (str/blank? ?csrf-token)
(warnf "SECURITY WARNING: no CSRF token available for use by Sente"))

Expand Down Expand Up @@ -813,8 +805,8 @@
(try
(WebSocket.
(enc/merge-url-with-query-string url
;; User params first (don't clobber impl. params):
(merge params {:client-id client-id})))
(merge params ; 1st (don't clobber impl.):
{:client-id client-id})))
(catch js/Error e
(errorf e "WebSocket js/Error")
nil))]
Expand Down Expand Up @@ -888,17 +880,23 @@
(when ?cb-fn (?cb-fn :chsk/closed)))

;; TODO Buffer before sending (but honor `:flush?`)
(do
(let [csrf-token (:csrf-token @state_)]
(ajax-lite url
(merge ajax-opts
{:method :post :timeout-ms ?timeout-ms
:resp-type :text ; We'll do our own pstr decoding
:headers
(merge (:headers ajax-opts) ; 1st (don't clobber impl.):
{:X-CSRF-Token csrf-token})

:params
(let [ppstr (pack packer (meta ev) ev (when ?cb-fn :ajax-cb))]
(merge
params ; User params first (don't clobber impl. params):
(merge params ; 1st (don't clobber impl.):
{:_ (enc/now-udt) ; Force uncached resp
:csrf-token (:csrf-token @state_)

;; A duplicate of X-CSRF-Token for user's convenience and
;; for back compatibility with earlier CSRF docs:
:csrf-token csrf-token

;; Just for user's convenience here. non-lp-POSTs don't
;; actually need a client-id for Sente's own implementation:
Expand Down Expand Up @@ -962,7 +960,7 @@
;; Note that user params here are actually POST params for
;; convenience. Contrast: WebSocket params sent as query
;; params since there's no other choice there.
params ; User params first (don't clobber impl. params)
params ; 1st (don't clobber impl.):

{:_ (enc/now-udt) ; Force uncached resp
:client-id client-id}
Expand Down

0 comments on commit bd833d2

Please sign in to comment.