|
369 | 369 | (allow-origin? #{"http://site.com"} {:headers {"referer" "http://attacker.com/"}}) |
370 | 370 | (allow-origin? #{"http://site.com"} {:headers {"referer" "http://site.com.attacker.com/"}})) |
371 | 371 |
|
| 372 | +(def ^:private sente-csrf-token-prefix "sente-csrf-token-") |
| 373 | + |
372 | 374 | (defn make-channel-socket-server! |
373 | 375 | "Takes a web server adapter[1] and returns a map with keys: |
374 | 376 |
|
|
633 | 635 | ;; undefined): |
634 | 636 | nil) |
635 | 637 |
|
| 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 | + |
636 | 652 | bad-csrf? |
637 | 653 | (fn [ring-req] |
638 | 654 | (if (nil? csrf-token-fn) ; Provides a way to disable CSRF check |
|
642 | 658 | (or |
643 | 659 | (get-in ring-req [:params :csrf-token]) |
644 | 660 | (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))] |
646 | 663 |
|
647 | 664 | (not |
648 | 665 | (enc/const-str= |
|
1316 | 1333 | (enc/oget @?node-npm-websocket_ "w3cwebsocket"))] |
1317 | 1334 |
|
1318 | 1335 | (delay |
1319 | | - (let [socket (WebSocket. uri-str)] |
| 1336 | + (let [protocols (:sec-websocket-protocol headers) |
| 1337 | + socket (WebSocket. uri-str protocols)] |
1320 | 1338 | (doto socket |
1321 | 1339 | (aset "onerror" on-error) |
1322 | 1340 | (aset "onmessage" on-message) ; Nb receives both push & cb evs! |
|
1569 | 1587 | {:on-error on-error |
1570 | 1588 | :on-message on-message |
1571 | 1589 | :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)))) |
1573 | 1599 | :uri-str |
1574 | 1600 | (enc/merge-url-with-query-string url |
1575 | 1601 | (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}))})) |
1579 | 1603 |
|
1580 | 1604 | (catch #?(:clj Throwable :cljs :default) t |
1581 | 1605 | (timbre/errorf t "Error creating WebSocket client") |
|
0 commit comments