Skip to content

Commit ab7d90f

Browse files
committed
Pass CSRF token using Sec-WebSocket-Protocol header
The proposed change tries to respect other values in the Sec-WebSocket-Protocol header, that the caller may have set in the `headers` option when calling `make-channel-socket-client!` [Re: #418]
1 parent e4cba96 commit ab7d90f

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

src/taoensso/sente.cljc

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@
369369
(allow-origin? #{"http://site.com"} {:headers {"referer" "http://attacker.com/"}})
370370
(allow-origin? #{"http://site.com"} {:headers {"referer" "http://site.com.attacker.com/"}}))
371371

372+
(def ^:private sente-csrf-token-prefix "sente-csrf-token-")
373+
372374
(defn make-channel-socket-server!
373375
"Takes a web server adapter[1] and returns a map with keys:
374376
@@ -633,6 +635,20 @@
633635
;; undefined):
634636
nil)
635637

638+
sente-csrf-token-pred
639+
(fn [s]
640+
(when (str/starts-with? s sente-csrf-token-prefix)
641+
(subs s (count sente-csrf-token-prefix))))
642+
643+
ws-csrf-token
644+
(fn [ring-req]
645+
(let [ws? (= "websocket" (get-in ring-req [:headers "upgrade"]))
646+
sec-websocket-protocol (get-in ring-req [:headers "sec-websocket-protocol"])
647+
protocol-vals (when (and ws? (string? sec-websocket-protocol))
648+
(-> sec-websocket-protocol
649+
(str/split #", *")))]
650+
(some sente-csrf-token-pred protocol-vals)))
651+
636652
bad-csrf?
637653
(fn [ring-req]
638654
(if (nil? csrf-token-fn) ; Provides a way to disable CSRF check
@@ -642,7 +658,8 @@
642658
(or
643659
(get-in ring-req [:params :csrf-token])
644660
(get-in ring-req [:headers "x-csrf-token"])
645-
(get-in ring-req [:headers "x-xsrf-token"]))]
661+
(get-in ring-req [:headers "x-xsrf-token"])
662+
(ws-csrf-token ring-req))]
646663

647664
(not
648665
(enc/const-str=
@@ -1316,7 +1333,8 @@
13161333
(enc/oget @?node-npm-websocket_ "w3cwebsocket"))]
13171334

13181335
(delay
1319-
(let [socket (WebSocket. uri-str)]
1336+
(let [protocols (:sec-websocket-protocol headers)
1337+
socket (WebSocket. uri-str protocols)]
13201338
(doto socket
13211339
(aset "onerror" on-error)
13221340
(aset "onmessage" on-message) ; Nb receives both push & cb evs!
@@ -1569,13 +1587,19 @@
15691587
{:on-error on-error
15701588
:on-message on-message
15711589
:on-close on-close
1572-
:headers headers
1590+
:headers (update headers :sec-websocket-protocol
1591+
(fn [x]
1592+
(let [csrf-token (str sente-csrf-token-prefix
1593+
(get-client-csrf-token-str :dynamic
1594+
(:csrf-token @state_)))]
1595+
(cond
1596+
(string? x) [x csrf-token]
1597+
(coll? x) (conj x csrf-token)
1598+
:else csrf-token))))
15731599
:uri-str
15741600
(enc/merge-url-with-query-string url
15751601
(merge params ; 1st (don't clobber impl.):
1576-
{:client-id client-id
1577-
:csrf-token (get-client-csrf-token-str :dynamic
1578-
(:csrf-token @state_))}))}))
1602+
{:client-id client-id}))}))
15791603

15801604
(catch #?(:clj Throwable :cljs :default) t
15811605
(timbre/errorf t "Error creating WebSocket client")

0 commit comments

Comments
 (0)