Verified Commit 9c23d265 authored by Snorre Magnus Davøen's avatar Snorre Magnus Davøen 💬
Browse files

Use deps.edn (clojure tools deps) to specify dependencies

To make library consumeable by tools deps based projects the
dependencies are now specified using a deps.edn file. This file is then
consumed by leiningen via the lein tools deps plugin.

Test dependencies are specified directly in the leiningen project.clj
Signed-off-by: Snorre Magnus Davøen's avatarSnorre Magnus Davøen <>
parent 1c495cde
Pipeline #13756 failed with stage
in 23 seconds
......@@ -9,3 +9,4 @@ pom.xml.asc
\ No newline at end of file
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.9.0"}
buddy/buddy-core {:mvn/version "1.5.0"}
buddy/buddy-sign {:mvn/version "3.0.0"}
org.clojure/data.json {:mvn/version "0.2.6"}
org.clojure/algo.generic {:mvn/version "0.1.3"}
invetica/uri {:mvn/version "0.5.0"}}}
......@@ -3,12 +3,9 @@
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.9.0"]
[buddy/buddy-core "1.5.0"]
[buddy/buddy-sign "3.0.0"]
[org.clojure/data.json "0.2.6"]
[org.clojure/algo.generic "0.1.3"]
[invetica/uri "0.5.0"]]
:middleware [lein-tools-deps.plugin/resolve-dependencies-with-deps-edn]
:plugins [[lein-tools-deps "0.4.1"]]
:lein-tools-deps/config {:config-files [:project]}
:profiles {:test {:resource-paths ["test-resources"]
:dependencies [[org.clojure/test.check "0.9.0"]
[clj-time "0.14.4"]
......@@ -12,20 +12,21 @@
(def jwtregex #"^[a-zA-Z0-9\-_=]+?\.[a-zA-Z0-9\-_=]+?\.[a-zA-Z0-9\-_=]+?$")
(s/def ::sub (s/nilable :no.nsd.authorizer/uuid))
(s/def ::sub (s/nilable string?))
(s/def ::kid string?)
(s/def ::kid (s/with-gen (s/nilable string?)
#(s/gen #{"test-key"})))
(s/def ::scope (s/nilable string?))
(s/def ::scopes (s/nilable (s/coll-of string? :kind set?)))
(s/def ::exp (s/and integer?
(s/def ::exp (s/nilable (s/and integer?
(s/def ::kty (s/with-gen (s/and string?
#(= "RSA" %))
#(s/gen #{"RSA"})))
(s/def ::kty (s/with-gen (s/nilable (s/and string?
#(= "RSA" %)))
#(s/gen #{"RSA" nil})))
(s/def ::n (s/with-gen string?
#(s/gen #{;;valid:
......@@ -35,13 +36,16 @@
(s/def ::e string?)
(s/def ::subject (s/nilable (s/keys :req-un [::sub ::exp]
:opt-un [::scope
(s/def ::claims (s/nilable (s/keys :opt-un [::exp
(s/def ::jwt (s/nilable (s/and string?
#(re-matches jwtregex %))))
(s/def ::jwt-header (s/keys :req-un [::kid ::kty]))
(s/def ::jwk (s/keys :req-un [::kty ::e ::n ::kid]))
(s/def ::RSAPublicKey keys/public-key?)
......@@ -53,12 +57,15 @@
#(s/gen #{(resource "jwks.json")
(resource "jwks-other.json")})))
(s/def ::jwks-url (s/or :url :invetica.uri/absolute-uri
:resource ::resource))
(s/fdef jwks-edn->public-keys
:args (s/cat :jwks (s/coll-of ::jwk :type vector?))
:ret ::key-store)
(defn jwks-edn->public-keys
(defn- jwks-edn->public-keys
"Transform vector of json-web-keys to map of kid -> PublicKey pairs."
(->> json-web-keys
......@@ -70,18 +77,23 @@
(s/fdef fetch-keys
:args (s/cat :jwks-url (s/or :url :invetica.uri/absolute-uri
:resource ::resource))
:ret ::key-store)
(defn fetch-keys
:args (s/cat :jwks-url ::jwks-url)
:ret (s/with-gen ::key-store
#(s/gen #{(->> (resource "jwks.json")
((fn [jwks-string] (json/read-str jwks-string :key-fn keyword)))
(defn- fetch-keys
"Fetches the jwks from the supplied jwks-url and converts to java Keys.
Returns a map keyed on key-id where each value is a RSAPublicKey object"
(->> jwks-url
(#(json/read-str % :key-fn keyword))
(try (->> jwks-url
(#(json/read-str % :key-fn keyword))
(catch Exception e false)))
(def public-keys
......@@ -90,24 +102,22 @@
(atom {}))
(defn refresh-keys
"Fetches keys and updates key store (atom)"
(reset! public-keys
(fetch-keys jwks-url)))
(s/fdef resolve-key
:args (s/cat :jwks-url ::jwks-url
:jwt-header ::jwt-header)
:ret ::RSAPublicKey)
(defn resolve-key
"Returns given jwks-url and :kid in jwt-header.
If no key is found refreshes"
[jwks-url jwt-header]
(let [key-fn (fn [] (get (deref public-keys) (:kid jwt-header)))]
(let [key-fn (fn [] (get @public-keys (:kid jwt-header)))]
(if-let [key (key-fn)]
(do (reset! public-keys (fetch-keys jwks-url))
(do (reset! public-keys (or (fetch-keys jwks-url) @public-keys))
(if-let [key (key-fn)]
(throw (ex-info "Could not locate public key corresponding to jwt header's kid."
(throw (ex-info (str "Could not locate public key corresponding to jwt header's kid: " (:kid jwt-header))
{:type :validation :cause :unknown-key})))))))
......@@ -6,7 +6,6 @@
[ :refer [resource]]
[clojure.test :refer [deftest testing is]]))
(def example-jwt "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c")
......@@ -54,14 +53,6 @@ vLu9XxKFHYlWPccluz3pqDfaGNPO12968DAldwvAV6hTGgx7oMaNPu0UltgD/aaj
(is (nil? (re-matches clj-jwt/jwtregex "ab12356723cdb.1235412513")))))
(deftest refresh-public-keys!
(testing "Repopulates the keystore"
(is (with-redefs [clj-jwt/public-keys (atom {})
clj-jwt/fetch-keys (fn [x] (identity {:foo :bar}))]
(not (empty? (do (clj-jwt/refresh-keys "")
(deftest unsign-jwt
(testing "Unsigns jwt and returns payload"
(is (= (with-redefs [clj-jwt/public-keys (atom {"test-key" ec-pubkey})]
......@@ -44,7 +44,9 @@ vLu9XxKFHYlWPccluz3pqDfaGNPO12968DAldwvAV6hTGgx7oMaNPu0UltgD/aaj
(def sample-claims {:sub "f750bd26-ae85-4808-8f9a-dcc964fc8664"
:exp (time/plus (time/now) (time/minutes 30))})
(def untestable-funs ['no.nsd.clj-jwt/fetch-keys])
(def untestable-funs ['no.nsd.clj-jwt/fetch-keys
(defn generate-jwt
[claims key]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment