Last active
August 30, 2017 22:18
-
-
Save raymcdermott/1f38ec455df433b96da789a70a4dd346 to your computer and use it in GitHub Desktop.
IODC Discovery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; TODO: have a way to have this list provided / augmented by users | |
(def ^:private oidc-discovery | |
"Map from TLDs to discovery endpoints" | |
{"auth0.com" ".well-known/jwks.json" | |
"google.com" ".well-known/openid-configuration"}) | |
(defn- get-jwt-data | |
"Obtain JWT related data and parse it into a Clojure map" | |
[endpoint] | |
(try | |
(-> @(client/get endpoint) | |
:body | |
bytes/to-string | |
string->edn) | |
(catch Exception e | |
; TODO 'proper' error handling | |
(println "Exception " e)))) | |
(def ^:private one-day | |
(* 1000 ;milliseconds -> seconds | |
60 ;seconds -> minutes | |
60 ;mins -> hours | |
24)) | |
;; It is not efficient to obtain these discovery docs on every verification | |
;; Compose the behaviour of these two caches to limit the number of and length of time | |
;; that certs that can be held in the cache | |
(def ^:private discovery-cache (atom (-> {} | |
(cache/fifo-cache-factory) | |
(cache/ttl-cache-factory :ttl one-day)))) | |
(defn jwt-discovery-info | |
"Obtain the JWKs based on the issuer URL, cache the result" | |
[issuer-url] | |
(when-let [domain (last (string/split issuer-url #"/"))] | |
(when-let [discovery-url (some->> (first (keep #(re-find (re-pattern %) domain) | |
(keys oidc-discovery))) | |
(get oidc-discovery) | |
(str issuer-url))] | |
(if (cache/has? @discovery-cache discovery-url) | |
(get (cache/hit @discovery-cache discovery-url) discovery-url) | |
(when-let [discovery-doc (get-jwt-data discovery-url)] | |
(let [updated-cache (swap! discovery-cache #(cache/miss % discovery-url discovery-doc))] | |
(get updated-cache discovery-url))))))) | |
(defn cert->pem | |
[cert] | |
(keys/str->public-key | |
(str "-----BEGIN CERTIFICATE-----\n" | |
(string/join "\n" (string/join "\n" (re-seq #".{1,64}" cert))) | |
"\n-----END CERTIFICATE-----\n"))) | |
; ---------->>>>>>> USAGE | |
(defn jwt-signing-info | |
[issuer kid] | |
(when-let [discovery-doc (jwt-discovery-info issuer)] | |
(when-let [signing-key (first (filter #(= kid (:kid %)) (:keys discovery-doc)))] | |
(let [public-key (cert->pem (first (:x5c signing-key))) | |
alg (keyword (string/lower-case (:alg signing-key)))] | |
{:key public-key :alg alg})))) | |
(defn verify-jwt | |
[token] | |
(let [decoded-jwt (decoded-jwt token) | |
issuer (get-in decoded-jwt [:payload :iss]) | |
kid (get-in decoded-jwt [:header :kid])] | |
(when-let [jwt-signing-info (jwt-signing-info issuer kid)] | |
(jwt/unsign token (:key jwt-signing-info) {:alg (:alg jwt-signing-info)})))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment