Skip to content

Commit

Permalink
Add :leeway option to jwt.
Browse files Browse the repository at this point in the history
This allows specify some leeway for jwt claims
validation.
  • Loading branch information
niwinz committed Aug 2, 2017
1 parent d19e4f4 commit 457bfdc
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
19 changes: 14 additions & 5 deletions src/buddy/sign/jwt.clj
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,37 @@
[buddy.sign.util :as util]
[cheshire.core :as json]))

(defn- validate-claims [claims {:keys [max-age iss aud now] :or
{now (util/now)}}]

(defn- validate-claims

This comment has been minimized.

Copy link
@delitescere

delitescere Aug 3, 2017

Contributor

Probably deserves some docstring now.

This comment has been minimized.

Copy link
@delitescere

delitescere Aug 3, 2017

Contributor
"Checks the issuer in the `:iss` claim against one of the allowed issuers in the passed `:iss`. Passed `:iss` may be a string or a vector of strings.
If no `:iss` is passed, this check is not performed.

Checks one or more audiences in the `:aud` claim against the single valid audience in the passed `:aud`.
If no `:aud` is passed, this check is not performed.

Checks the `:exp` claim is not less than the passed `:now`, with a leeway of the passed `:leeway`.
If no `:exp` claim exists, this check is not performed.

Checks the `:nbf` claim is less than the passed `:now`, with a leeway of the passed `:leeway`.
If no `:nbf` claim exists, this check is not performed.

Checks the passed `:now` is greater than the `:iat` claim plus the passed `:max-age`. If no `:iat` claim exists, this check is not performed.

A check that fails raises an exception with `:type` of `:validation` and `:cause` indicating which check failed.

`:now` is an integer POSIX time and defaults to the current time.
`:leeway` is an integer number of seconds and defaults to zero."
[claims {:keys [max-age iss aud now leeway] :or {now (util/now) leeway 0}}]
(let [now (util/to-timestamp now)]

;; Check the `:iss` claim.
(when (and iss (let [iss-claim (:iss claims)]
(if (coll? iss)
(not-any? #{iss-claim} iss)
(not= iss-claim iss))))
(throw (ex-info (str "Issuer does not match " iss)
{:type :validation :cause :iss})))

;; Check the `:aud` claim.
(when (and aud (let [aud-claim (:aud claims)]
(if (coll? aud-claim)
(not-any? #{aud} aud-claim)
(not= aud aud-claim))))
(throw (ex-info (str "Audience does not match " aud)
{:type :validation :cause :aud})))
(when (and (:exp claims) (>= now (:exp claims)))

;; Check the `:exp` claim.
(when (and (:exp claims) (<= (:exp claims) (- now leeway)))
(throw (ex-info (format "Token is expired (%s)" (:exp claims))
{:type :validation :cause :exp})))
(when (and (:nbf claims) (< now (:nbf claims)))

;; Check the `:nbf` claim.
(when (and (:nbf claims) (> (:nbf claims) (+ now leeway)))
(throw (ex-info (format "Token is not yet valid (%s)" (:nbf claims))
{:type :validation :cause :nbf})))

;; Check the `:max-age` option.
(when (and (:iat claims) (number? max-age) (> (- now (:iat claims)) max-age))
(throw (ex-info (format "Token is older than max-age (%s)" max-age)
{:type :validation :cause :max-age})))
Expand Down
2 changes: 1 addition & 1 deletion src/buddy/sign/util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
(.invoke method this (make-array Object 0)))})))

(defn now
"Get a current timestamp."
"Get a current timestamp in seconds."
[]
(quot (System/currentTimeMillis) 1000))

Expand Down
6 changes: 5 additions & 1 deletion test/buddy/sign/jwt_tests.clj
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,18 @@
signed (make-jwt-fn candidate)]
(unsign-exp-succ signed candidate {:now 0})
(unsign-exp-succ signed candidate {:now 9})
(unsign-exp-succ signed candidate {:now 10 :leeway 1})
(unsign-exp-fail signed :exp {:now 10})
(unsign-exp-fail signed :exp {:now 11})))
(unsign-exp-fail signed :exp {:now 11})
(unsign-exp-fail signed :exp {:now 12 :leeway 1})))

(testing ":nbf claim validation"
(let [candidate {:foo "bar" :nbf 10}
signed (make-jwt-fn candidate)]
(unsign-exp-fail signed :nbf {:now 0})
(unsign-exp-fail signed :nbf {:now 8 :leeway 1})
(unsign-exp-fail signed :nbf {:now 9})
(unsign-exp-succ signed candidate {:now 9 :leeway 1})
(unsign-exp-succ signed candidate {:now 10})
(unsign-exp-succ signed candidate {:now 11})))

Expand Down

0 comments on commit 457bfdc

Please sign in to comment.