Last active
September 24, 2015 19:41
-
-
Save wagjo/27ce6a34d5d5257a0790 to your computer and use it in GitHub Desktop.
JWT Parsing in Dunaj
This file contains 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
(ns foo.core | |
(:api dunaj) | |
(:require [dunaj.host.int :refer [i== iDOT]] | |
[dunaj.host.array :as dha] | |
[dunaj.format.base64 :refer [base64-safe]] | |
[dunaj.coll.recipe :refer [concat*]] | |
[dunaj.concurrent.port :refer [reduce! onto-chan!]])) | |
(def+ ByteColl [java.lang.Byte]) ;; type signature | |
(defn split-token :- KeywordMap | |
"Parses JWT token and returns map with its parts." | |
[token :- ByteColl] | |
(let [parts (vec (partition-by #(i== (iDOT) %) token)) | |
kjson (assoc json :key-decode-fn keyword) | |
pf #(parse-whole kjson (parse utf-8 (parse base64-safe %)))] | |
{:signed-part (concat* (take 3 parts)) | |
:header (pf (first parts)) | |
:claims (pf (nth parts 2)) | |
:signature (parse base64-safe (nth parts 4 nil))})) | |
(defn secret-sign :- ByteColl | |
"Returns the result of signing data with secret." | |
[alg :- String, secret :- ByteColl, data :- ByteColl] | |
(let [secret-key (javax.crypto.spec.SecretKeySpec. (dha/byte-array secret) alg) | |
hmac (javax.crypto.Mac/getInstance alg)] | |
(.init hmac secret-key) | |
(dha/adapt (.doFinal hmac (dha/byte-array data))))) | |
(defn jwt :- ByteColl | |
[claims :- {}, secret :- ByteColl] | |
(let [pf #(print base64-safe (print utf-8 (print-one json %))) | |
header {:typ "JWT" :alg "HS256"} | |
signed-part (concat (pf header) [(iDOT)] (pf claims)) | |
signature (secret-sign "HmacSHA256" secret signed-part)] | |
(vec (concat signed-part [(iDOT)] (print base64-safe signature))))) | |
(def my-token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ") | |
(def my-secret "secret") | |
;;;; Scratch | |
(scratch [] | |
;; Parsing | |
(def token-bytes (print utf-8 my-token)) | |
(def parsed-token (split-token token-bytes)) | |
parsed-token | |
;; {:signed-part #object[dunaj.coll.helper.Reduciblecbus 0x73002b3d "dunaj.coll.helper.Reduciblecbus@73002b3d"], | |
;; :header {:alg "HS256", :typ "JWT"}, | |
;; :claims {:sub "1234567890", :name "John Doe", :admin true}, | |
;; :signature #object[dunaj.coll.helper.Reduciblecbus 0x28a24be3 "dunaj.coll.helper.Reduciblecbus@28a24be3"] | |
;; } | |
(:claims parsed-token) | |
;; {:sub "1234567890", :name "John Doe", :admin true} | |
;; Verification | |
(vec (:signature parsed-token)) | |
;; [76 -107 64 -9 -109 -85 51 -79 54 112 22 -101 -33 68 76 30 -79 -61 112 71 -15 -114 -122 25 -127 -31 78 52 88 123 30 4] | |
(def secret-bytes (print utf-8 my-secret)) | |
(secret-sign "HmacSHA256" secret-bytes (:signed-part parsed-token)) | |
;; (76 -107 64 -9 -109 -85 51 -79 54 112 22 -101 -33 68 76 30 -79 -61 112 71 -15 -114 -122 25 -127 -31 78 52 88 123 30 4) | |
(= (seq (vec (:signature parsed-token))) | |
(seq (secret-sign "HmacSHA256" secret-bytes (:signed-part parsed-token)))) | |
;; true | |
;; Token creation | |
(def new-token-bytes (jwt {:sub "1234567890", :name "John Doe", :admin false} secret-bytes)) | |
(def new-token (str (parse utf-8 new-token-bytes))) | |
;; eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOmZhbHNlfQ==.S_mcs280KaxVTd5I3-kPeSwyrtOXZJHqfPF5RH2gQV0= | |
;; Example on using transducers | |
(let [xf (comp (parse base64-safe) | |
(parse utf-8) | |
(parse json)) | |
c (chan 100 xf) | |
v (vec (print utf-8 "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9"))] | |
(<!! (onto-chan! c v)) | |
(thread (pp! (<!! (reduce! conj [] c)))) | |
(close! c)) | |
;; [{"typ" "JWT", "alg" "HS256"} {"sub" "1234567890", "name" "John Doe", "admin" true}] | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment