 (defn sign
   "Sign arbitrary length string/byte array using
   json web token/signature."
-  [claims pkey & [{:keys [alg exp nbf iat headers] :or {alg :hs256 headers {}}}]]
+  ;; The exp nbf and iat keys in the options are deprecated
+  ;; and will be removed in the next version.
+  [claims pkey & [{:keys [alg typ] :or {alg :hs256 typ :jws} :as opts}]]
   {:pre [(map? claims)]}
-  (let [header (encode-header alg headers)
-        claims (encode-claims claims exp nbf iat)
+  (let [header (encode-header alg typ)
+        claims (encode-claims claims opts)
         signature (calculate-signature {:key pkey
                                         :alg alg
                                         :header header

  [data]
  (into {} (remove (comp nil? second) data)))

(defn encode-header
  "Encode jws header"
  [alg extra]
  (let [algorithm (.toUpperCase (name alg))]
    (-> (merge {:alg algorithm :typ "JWS"} extra)
        (json/generate-string)
        (codecs/str->bytes)
        (codecs/bytes->safebase64))))

(defn encode-claims
  "Encode jws claims."
  [input exp nbf iat]
  (let [additionalclaims (-> (normalize-nil-claims {:exp exp :nbf nbf :iat iat})
                             (normalize-date-claims))]
    (-> (normalize-date-claims input)
        (merge additionalclaims)

(defn unsign
  "Given a signed message, verify it and return
  the decoded claims."
  ([input pkey] (unsign input pkey {}))
  ([input pkey opts]
   (let [[header claims signature] (str/split input #"\." 3)
         {:keys [alg]} (parse-header header opts)
         signature (codecs/safebase64->bytes signature)]
    (when-not (verify-signature {:key pkey :signature signature
                                 :alg alg :header header :claims claims})
      (throw+ {:type :validation :cause :auth :message "Message seems corrupt or manipulated."}))
    (parse-claims claims opts))))

(defn encode
  "Sign arbitrary length string/byte array using
