diff --git a/deps/db-sync/src/logseq/db_sync/worker/auth.cljs b/deps/db-sync/src/logseq/db_sync/worker/auth.cljs index ce6668adc1..5e1de6c4d6 100644 --- a/deps/db-sync/src/logseq/db_sync/worker/auth.cljs +++ b/deps/db-sync/src/logseq/db_sync/worker/auth.cljs @@ -1,6 +1,7 @@ (ns logseq.db-sync.worker.auth (:require [clojure.string :as string] - [logseq.common.authorization :as authorization])) + [logseq.common.authorization :as authorization] + [promesa.core :as p])) (defn- bearer-token [auth-header] (when (and (string? auth-header) (string/starts-with? auth-header "Bearer ")) @@ -30,8 +31,21 @@ (catch :default _ nil))) +(def ^:private recoverable-auth-errors + #{"invalid" "iss not found" "aud not found" "exp" "kid"}) + +(defn- recoverable-auth-error? + [error] + (when error + (let [message (or (ex-message error) (some-> error .-message))] + (contains? recoverable-auth-errors message)))) + (defn auth-claims [request env] (let [token (token-from-request request)] (if (string? token) - (authorization/verify-jwt token env) - (js/Promise.resolve nil)))) + (-> (authorization/verify-jwt token env) + (p/catch (fn [error] + (if (recoverable-auth-error? error) + nil + (p/rejected error))))) + (p/resolved nil)))) diff --git a/deps/db-sync/test/logseq/db_sync/worker_auth_test.cljs b/deps/db-sync/test/logseq/db_sync/worker_auth_test.cljs index 518c86caef..507cd10708 100644 --- a/deps/db-sync/test/logseq/db_sync/worker_auth_test.cljs +++ b/deps/db-sync/test/logseq/db_sync/worker_auth_test.cljs @@ -27,3 +27,32 @@ (p/catch (fn [error] (is false (str error)) (done))))))) + +(deftest auth-claims-expired-token-returns-nil-test + (async done + (let [request (js/Request. "http://localhost/graphs" + #js {:headers #js {"authorization" "Bearer expired-token"}})] + (-> (p/with-redefs [authorization/verify-jwt + (fn [_token _env] + (p/rejected (ex-info "exp" {})))] + (p/let [claims (auth/auth-claims request #js {})] + (is (nil? claims)))) + (p/then (fn [] (done))) + (p/catch (fn [error] + (is false (str error)) + (done))))))) + +(deftest auth-claims-jwks-error-propagates-test + (async done + (let [request (js/Request. "http://localhost/graphs" + #js {:headers #js {"authorization" "Bearer broken-token"}})] + (-> (p/with-redefs [authorization/verify-jwt + (fn [_token _env] + (p/rejected (ex-info "jwks" {})))] + (auth/auth-claims request #js {})) + (p/then (fn [_] + (is false "expected rejection when jwks fetch fails") + (done))) + (p/catch (fn [error] + (is (= "jwks" (ex-message error))) + (done)))))))