|
2 | 2 |
|
3 | 3 | (ns juxt.pass.alpha.authentication
|
4 | 4 | (:require
|
5 |
| - [jsonista.core :as json] |
6 | 5 | [clojure.tools.logging :as log]
|
7 |
| - [crypto.password.bcrypt :as password] |
| 6 | + [clojure.walk :as walk] |
8 | 7 | [crux.api :as x]
|
| 8 | + [crypto.password.bcrypt :as password] |
| 9 | + [jsonista.core :as json] |
9 | 10 | [juxt.reap.alpha.decoders :as reap]
|
10 | 11 | [juxt.reap.alpha.rfc7235 :as rfc7235]
|
11 |
| - [ring.util.codec :refer [form-decode url-decode]] |
12 |
| - [ring.middleware.cookies :refer [cookies-request cookies-response]])) |
| 12 | + [ring.middleware.cookies :refer [cookies-request cookies-response]] |
| 13 | + [ring.util.codec :refer [form-decode]]) |
| 14 | + (:import |
| 15 | + (java.time Instant))) |
13 | 16 |
|
14 | 17 | (alias 'http (create-ns 'juxt.http.alpha))
|
15 | 18 | (alias 'pass (create-ns 'juxt.pass.alpha))
|
|
23 | 26 | (.nextBytes SECURE-RANDOM bytes)
|
24 | 27 | (.encodeToString BASE64-ENCODER bytes)))
|
25 | 28 |
|
26 |
| -(defonce sessions-by-access-token (atom {})) |
27 |
| - |
28 |
| -(defn put-session! [k session ^java.time.Instant expiry-instant] |
29 |
| - (swap! sessions-by-access-token |
30 |
| - assoc k (assoc session |
31 |
| - ::expiry-instant expiry-instant))) |
32 |
| - |
33 |
| -(defn remove-session! [k] |
34 |
| - (swap! sessions-by-access-token |
35 |
| - dissoc k)) |
36 |
| - |
37 |
| -(defn expire-sessions! [date-now] |
38 |
| - (swap! sessions-by-access-token |
39 |
| - (fn [sessions] |
40 |
| - (into {} (remove #(.isAfter (.toInstant date-now) |
41 |
| - (-> % second (get ::expiry-instant))) |
42 |
| - sessions))))) |
43 |
| - |
44 |
| -(defn lookup-session [k date-now] |
45 |
| - (expire-sessions! date-now) |
46 |
| - (get @sessions-by-access-token k)) |
47 |
| - |
48 |
| -;;(identity @sessions-by-access-token) |
| 29 | +(defn put-session! [{::site/keys [crux-node base-uri start-date]} k session] |
| 30 | + (let [session (walk/keywordize-keys session)] |
| 31 | + (->> [[:crux.tx/put |
| 32 | + (merge |
| 33 | + (select-keys session [::pass/user ::pass/state ::pass/nonce ::pass/return-to]) |
| 34 | + {:crux.db/id (str base-uri "/site-session/" k) |
| 35 | + :juxt.site.alpha/type "SiteSession" |
| 36 | + ::expiry-instant |
| 37 | + (-> (if start-date (.toInstant start-date) (Instant/now)) |
| 38 | + (.plusSeconds (or (:expires_in session) 3600)))})]] |
| 39 | + (x/submit-tx crux-node) |
| 40 | + (x/await-tx crux-node)))) |
| 41 | + |
| 42 | +(defn remove-session! [{::site/keys [crux-node base-uri]} k] |
| 43 | + (->> [[:crux.tx/evict (str base-uri "/site-session/" k)]] |
| 44 | + (x/submit-tx crux-node) |
| 45 | + (x/await-tx crux-node))) |
| 46 | + |
| 47 | +(defn expire-sessions! [{::site/keys [crux-node db start-date]}] |
| 48 | + (->> (x/q db '{:find [ss expiry-instant] |
| 49 | + :where [[ss :juxt.site.alpha/type "SiteSession"] |
| 50 | + [ss ::expiry-instant expiry-instant]]}) |
| 51 | + (filter (fn [[_ expiry-instant]] |
| 52 | + (.isAfter (.toInstant start-date) expiry-instant))) |
| 53 | + (mapv (fn [[ss _]] [:crux.tx/evict ss])) |
| 54 | + (x/submit-tx crux-node) |
| 55 | + (x/await-tx crux-node))) |
| 56 | + |
| 57 | +(defn lookup-session [{::site/keys [db base-uri] :as req} k] |
| 58 | + (expire-sessions! req) |
| 59 | + (x/entity db (str base-uri "/site-session/" k))) |
49 | 60 |
|
50 | 61 | (defn token-response
|
51 |
| - [{::site/keys [received-representation resource start-date] |
| 62 | + [{::site/keys [received-representation resource] |
52 | 63 | ::pass/keys [subject] :as req}]
|
53 | 64 |
|
54 | 65 | ;; Check grant_type of posted-representation
|
|
84 | 95 | "user" (::pass/user subject)}
|
85 | 96 |
|
86 | 97 | _ (put-session!
|
| 98 | + req |
87 | 99 | access-token
|
88 |
| - (merge session subject) |
89 |
| - (.plusSeconds (.toInstant start-date) expires-in)) |
| 100 | + (merge session subject)) |
90 | 101 |
|
91 | 102 | body (.getBytes
|
92 | 103 | (str
|
|
145 | 156 | "token_type" "login"
|
146 | 157 | "expires_in" expires-in}]
|
147 | 158 | (put-session!
|
| 159 | + req |
148 | 160 | access-token
|
149 | 161 | (merge session {::pass/user user
|
150 |
| - ::pass/username username}) |
151 |
| - (.plusSeconds (.toInstant start-date) expires-in)) |
| 162 | + ::pass/username username})) |
152 | 163 | (-> req
|
153 | 164 | (assoc :ring.response/status 302
|
154 | 165 | :ring.response/body
|
|
236 | 247 | (some-> req
|
237 | 248 | ((fn [req] (assoc req :headers (get req :ring.request/headers))))
|
238 | 249 | cookies-request
|
239 |
| - :cookies (get "site_session") :value json/read-value) |
240 |
| - now (::site/start-date req)] |
| 250 | + :cookies (get "site_session") :value json/read-value)] |
241 | 251 |
|
242 | 252 | (or
|
243 | 253 | ;; Cookie
|
244 | 254 | (when access-token
|
245 |
| - (when-let [session (lookup-session access-token now)] |
| 255 | + (when-let [session (lookup-session req access-token)] |
246 | 256 | (->
|
247 | 257 | (select-keys session [::pass/user ::pass/username])
|
248 | 258 | (assoc ::pass/auth-scheme "Session"))))
|
|
276 | 286 | (log/error e)))
|
277 | 287 |
|
278 | 288 | "bearer"
|
279 |
| - (when-let [session (lookup-session token68 now)] |
| 289 | + (when-let [session (lookup-session req token68)] |
280 | 290 | (->
|
281 | 291 | (select-keys session [::pass/user ::pass/username])
|
282 | 292 | (assoc ::pass/auth-scheme "Bearer")))
|
|
0 commit comments