mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
✨ Add better approach for cookie token decoding
Remove unnecesary decoding for old tokens and add key identifier and versioning to cookie tokens for handle future changes.
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.http :as-alias http]
|
[app.http :as-alias http]
|
||||||
[app.http.errors :as errors]
|
[app.http.errors :as errors]
|
||||||
|
[app.tokens :as tokens]
|
||||||
[app.util.pointer-map :as pmap]
|
[app.util.pointer-map :as pmap]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[yetti.adapter :as yt]
|
[yetti.adapter :as yt]
|
||||||
@@ -272,9 +273,24 @@
|
|||||||
process-request
|
process-request
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(if-let [{:keys [type token] :as auth} (get-token request)]
|
(if-let [{:keys [type token] :as auth} (get-token request)]
|
||||||
(if-let [decode-fn (get decoders type)]
|
(let [decode-fn (get decoders type)]
|
||||||
|
(if (= type :cookie)
|
||||||
|
(let [metadata (tokens/decode-header token)]
|
||||||
|
;; NOTE: we only proceed to decode claims on new
|
||||||
|
;; cookie tokens. The old cookies dont need to be
|
||||||
|
;; decoded because they use the token string as ID
|
||||||
|
(if (and (= (:kid metadata) 1)
|
||||||
|
(= (:ver metadata) 1)
|
||||||
|
(some? decode-fn))
|
||||||
|
(assoc request ::http/auth-data (assoc auth
|
||||||
|
:claims (decode-fn token)
|
||||||
|
:metadata metadata))
|
||||||
|
(assoc request ::http/auth-data (assoc auth :metadata {:ver 0}))))
|
||||||
|
|
||||||
|
(if decode-fn
|
||||||
(assoc request ::http/auth-data (assoc auth :claims (decode-fn token)))
|
(assoc request ::http/auth-data (assoc auth :claims (decode-fn token)))
|
||||||
(assoc request ::http/auth-data auth))
|
(assoc request ::http/auth-data auth))))
|
||||||
|
|
||||||
request))]
|
request))]
|
||||||
|
|
||||||
(fn [request]
|
(fn [request]
|
||||||
|
|||||||
@@ -158,14 +158,15 @@
|
|||||||
|
|
||||||
(defn- assign-token
|
(defn- assign-token
|
||||||
[cfg session]
|
[cfg session]
|
||||||
(let [token (tokens/generate cfg
|
(let [claims {:iss "authentication"
|
||||||
{:iss "authentication"
|
|
||||||
:aud "penpot"
|
:aud "penpot"
|
||||||
:sid (:id session)
|
:sid (:id session)
|
||||||
:iat (:modified-at session)
|
:iat (:modified-at session)
|
||||||
:uid (:profile-id session)
|
:uid (:profile-id session)
|
||||||
:sso-provider-id (:sso-provider-id session)
|
:sso-provider-id (:sso-provider-id session)
|
||||||
:sso-session-id (:sso-session-id session)})]
|
:sso-session-id (:sso-session-id session)}
|
||||||
|
header {:kid 1 :ver 1}
|
||||||
|
token (tokens/generate cfg claims header)]
|
||||||
(assoc session :token token)))
|
(assoc session :token token)))
|
||||||
|
|
||||||
(defn create-fn
|
(defn create-fn
|
||||||
@@ -225,13 +226,14 @@
|
|||||||
[handler {:keys [::manager] :as cfg}]
|
[handler {:keys [::manager] :as cfg}]
|
||||||
(assert (manager? manager) "expected valid session manager")
|
(assert (manager? manager) "expected valid session manager")
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(let [{:keys [type token claims]} (get request ::http/auth-data)]
|
(let [{:keys [type token claims metadata]} (get request ::http/auth-data)]
|
||||||
(cond
|
(cond
|
||||||
(= type :cookie)
|
(= type :cookie)
|
||||||
(let [session (if-let [sid (:sid claims)]
|
(let [session (case (:ver metadata)
|
||||||
(read-session manager sid)
|
|
||||||
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
|
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
|
||||||
(read-session manager token))
|
0 (read-session manager token)
|
||||||
|
1 (some->> (:sid claims) (read-session manager))
|
||||||
|
nil)
|
||||||
|
|
||||||
request (cond-> request
|
request (cond-> request
|
||||||
(some? session)
|
(some? session)
|
||||||
@@ -240,7 +242,7 @@
|
|||||||
|
|
||||||
response (handler request)]
|
response (handler request)]
|
||||||
|
|
||||||
(if (renew-session? session)
|
(if (and session (renew-session? session))
|
||||||
(let [session (->> session
|
(let [session (->> session
|
||||||
(update-session manager)
|
(update-session manager)
|
||||||
(assign-token cfg))]
|
(assign-token cfg))]
|
||||||
@@ -248,11 +250,11 @@
|
|||||||
response))
|
response))
|
||||||
|
|
||||||
(= type :bearer)
|
(= type :bearer)
|
||||||
(let [session (if-let [sid (:sid claims)]
|
(let [session (case (:ver metadata)
|
||||||
(read-session manager sid)
|
|
||||||
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
|
;; BACKWARD COMPATIBILITY WITH OLD TOKENS
|
||||||
(read-session manager token))
|
0 (read-session manager token)
|
||||||
|
1 (some->> (:sid claims) (read-session manager))
|
||||||
|
nil)
|
||||||
request (cond-> request
|
request (cond-> request
|
||||||
(some? session)
|
(some? session)
|
||||||
(-> (assoc ::profile-id (:profile-id session))
|
(-> (assoc ::profile-id (:profile-id session))
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
[buddy.sign.jwe :as jwe]))
|
[buddy.sign.jwe :as jwe]))
|
||||||
|
|
||||||
(defn generate
|
(defn generate
|
||||||
[{:keys [::setup/props] :as cfg} claims]
|
([cfg claims] (generate cfg claims nil))
|
||||||
(assert (contains? cfg ::setup/props))
|
([{:keys [::setup/props] :as cfg} claims header]
|
||||||
|
(assert (contains? props :tokens-key) "expect props to have tokens-key")
|
||||||
|
|
||||||
(let [tokens-key
|
(let [tokens-key
|
||||||
(get props :tokens-key)
|
(get props :tokens-key)
|
||||||
@@ -27,7 +28,12 @@
|
|||||||
(d/without-nils)
|
(d/without-nils)
|
||||||
(t/encode))]
|
(t/encode))]
|
||||||
|
|
||||||
(jwe/encrypt payload tokens-key {:alg :a256kw :enc :a256gcm})))
|
(jwe/encrypt payload tokens-key {:alg :a256kw :enc :a256gcm :header header}))))
|
||||||
|
|
||||||
|
(defn decode-header
|
||||||
|
[token]
|
||||||
|
(ex/ignoring
|
||||||
|
(jwe/decode-header token)))
|
||||||
|
|
||||||
(defn decode
|
(defn decode
|
||||||
[{:keys [::setup/props] :as cfg} token]
|
[{:keys [::setup/props] :as cfg} token]
|
||||||
|
|||||||
Reference in New Issue
Block a user