-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathsession.clj
81 lines (67 loc) · 3.18 KB
/
session.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(ns juxt.pass.alpha.session
;; Copyright © 2022, JUXT LTD.
;; References --
;; [OWASP-SM]: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
(:require
[juxt.pass.alpha.authentication :as authz]
[ring.middleware.cookies :refer [cookies-request cookies-response]]
[clojure.tools.logging :as log])
(:import
(org.apache.http.client.utils URIBuilder)))
(alias 'http (create-ns 'juxt.http.alpha))
(alias 'pass (create-ns 'juxt.pass.alpha))
(alias 'site (create-ns 'juxt.site.alpha))
;; The id cookie is only used during the OAuth Authorization Flow using
;; OpenID Connect for Authentication. It is used to store the session-token-id
;; created before calling the authorize endpoint. The session is used to prevent
;; CSRF-attacks as it stores the random state and nonce values for comparison.
(defn ->cookie [session-token-id]
;; TODO: In local testing (against home.test) it seems that setting
;; SameSite=Strict means that the cookie doesn't get passed through. I think
;; it's because the first-party is being 'called' from Auth0, which means that
;; samesite=strict cookies aren't sent across. Note: I've tried replacing the
;; POST to /_site/login-with-github with a GET but to no avail (I've left it
;; at a GET as that seems more mainstream)
(format "id=%s; Path=/; Secure; HttpOnly; SameSite=Lax" session-token-id))
(defn set-cookie [req session-id]
(-> req
(update :ring.response/headers assoc "set-cookie" (->cookie session-id))))
(defn escalate-session
"If provided session-token-id! matches, create a new session with the matched identity"
[{::pass/keys [session-token-id!] :as req} matched-identity]
(let [session (authz/lookup-session req session-token-id!)
_ (assert session)
new-session-token-id! (authz/access-token)]
(authz/remove-session! req session-token-id!)
(authz/put-session!
req
new-session-token-id!
{::pass/user matched-identity
"access_token" new-session-token-id!
"expires_in" (* 24 3600)
"user" matched-identity})
(-> req
(set-cookie new-session-token-id!)
(update-in [:ring.response/headers "location"]
(fn [location]
(-> (new URIBuilder location)
(.addParameter "code" new-session-token-id!)
(.toString)))))))
(defn wrap-associate-session [h]
(fn [req]
(let [session-token-id!
(-> (assoc req :headers (get req :ring.request/headers))
cookies-request
:cookies (get "id") :value)
session (when session-token-id!
(authz/lookup-session req session-token-id!))
subject (some->
(select-keys session [::pass/user ::pass/username])
(assoc ::pass/auth-scheme "Session"))
req (cond-> req
;; The purpose of the trailing exclamation mark (!) is to
;; indicate sensitivity. Avoid logging sensitive data.
session-token-id! (assoc ::pass/session-token-id! session-token-id!)
session (assoc ::pass/session session)
subject (assoc ::pass/subject subject))]
(h req))))