alekcz / charmander

A set of libraries to make working with firebase easier in clojure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Inability to pass extra opts to jwt/unsign

lopezvit opened this issue · comments

The method jwt/unsign receives a third argument called opts. But when the method is called in the src/charmander/core.clj file it does it with the literal {:alg :rs256} making it impossible to pass other options like:

  • skip-validation
  • max-age
  • iss
  • aud
  • now
  • leeway

Also, it would be convenient to check for :iss and not just for :aud/:projectid, as that is what the firebase documentation is saying. Basically once :aud has been validated against the regex, you would just need to make sure that :iss is equal to "https://securetoken.google.com/" + :aud.

@lopezvit thanks for opening this issue. You're 100% spot on. I've made the following changes:

  1. Aligned validation to guideline here https://firebase.google.com/docs/auth/admin/verify-id-tokens

    (defn- validate-claims [data]
    (let [now (quot (System/currentTimeMillis) 1000)]
    (and
    (= (str "https://securetoken.google.com/" (:aud data)) (:iss data))
    (> (:exp data) now)
    (< (:iat data) now)
    (not (str/blank? (:sub data)))
    (< (:auth_time data) now))))

  2. Allowed optional parameter to passed through to jwt/unsign

If you're happy I'll push a snapshot for you to test with.

Thanks for your fast response.
I was planning to copy the code and just modify it myself, but since you have done the effort of modifying the library, I will use it as it is :)

Awesome give the snapshot a spin: [alekcz/charmander "1.0.2-SNAPSHOT"]. Will run a few tests today then push 1.0.2 a bit later.

I have also write an issue in #funcool/buddy-auth#89 because it would be awesome that your library could be used directly with buddy-auth, as it would solve all the problems I'm facing authenticating my app with firebase token.
Do you think it could be possible to add another public method that would only return the correct public key given a token?
something like:

(defn- get-token-payload
  "Retrieves payload from token. Payload is used for validation when not unsigning the message"
  [token]
  (let [token-array (str/split token #"\." 3)]
    (json/read-value (base64/decode (pad-token (second token-array))) mapper)))

(defn- return-keys
  "2nd Core library method. Validates token using projectid-regex and checks the times are correct. and returns public key."
  [projectid-regex token opts]
  (let [header  (get-token-header token)
        cert (keys/str->public-key ((keyword (:kid header)) @public-keys))
        unsigned-data (if (keys/public-key? cert) (get-token-payload token) nil)
        validated? (validate-claims unsigned-data)]
    (when validated?
      (verify-domain projectid-regex (format-result unsigned-data))
      cert)))

; public methods

(defn get-secret
  "Public method that makes sure the issuing domain is valid using a regex but return a public key instead of validating
  the signature, to use it with buddy-auth"
  [projectid-regex token]
  (try
    (if (nil? @public-keys)
      (do	(load-public-keys threadpool schedule-public-key-update) (return-keys projectid-regex token))
      (return-keys projectid-regex token))
    (catch Exception _ nil)))

  (defn validate-token
    "Public method that validates token and makes sure the issuing domain is also valid"
    [projectid-regex token & opts]
    (try
      (if (nil? @public-keys)
        (do	(load-public-keys threadpool schedule-public-key-update) (authenticate projectid-regex token (merge {} opts)))
        (authenticate projectid-regex token (merge {} opts)))
      (catch Exception _ nil)))

That way it will be easy to create a wrapper around get-secret that would receive only the token.
Important note: My code hasn't been tested, it is just to show what I meant.

Pushed v1.0.2