Liking cljdoc? Tell your friends :D

ring-jwt

Clojars Project

Ring middleware for parsing, decoding and verifying a JWS-signed JWT token from the incoming request. (There is no explicit support for JWE currently.)

Built on top of the excellent auth0 JWT library.

IMPORTANT: For those upgrading from versions older than 2.4.0: This version introduced a potentially breaking change to the reject-missing-token? flag. Instead of defaulting to false it now defaults to true. So, if you are not already explicitly setting the field in your configuration, you will need to add an explicit :reject-missing-token? false.

Once wired into your ring server, the middleware will:

  • Search for a JWT token on each incoming request.
    • By default, it will parse the bearer token from the Authorization HTTP header but this behaviour can be overridden using the find-token-fn setting (see usage below).
  • Will add the claims it finds in the token as a clojure map against the :claims key on the incoming request.
  • Add an empty :claims map to the request if no token is found.
  • Respond with a 401 if the JWS signature in the token cannot be verified.
  • Respond with a 401 if the token has expired (i.e. the exp claim indicates a time in the past).
    • A leeway can be specified for this check with the leeway-seconds setting (see usage below).
  • Respond with a 401 if the token will only be active in the future (i.e. the nbf claim indicates a time in the future)
    • As for exp, the leeway-seconds setting can be used to introduce a leeway on this check.

IMPORTANT: by default a missing token will simply cause authentication to be skipped - to override this behaviour set the reject-missing-token? setting (see below). This to allow for the common scenario where authentication is only required on a subset of endpoints (e.g. to skip authentication on a healthcheck endpoint). It is therefore expected that any token would then be used for authorization: and a missing token would cause this authorization to fail.

Usage

(require '[ring.middleware.jwt :as jwt])

(defn handler [request]
  (response {:foo "bar"}))

(jwt/wrap-jwt handler {:issuers {"https://some/issuer"    {:alg    :HS256
                                                           :secret "asecret"}
                                 "https://another/issuer" {:alg          :RS256
                                                           :jwk-endpoint "https://some/jwks/endpoint"}
                                 :no-issuer               {:alg    :HS256
                                                           :secret "anothersecret"}}})

Options:

  • :issuers (mandatory): A map of issuer->cryptographic algorithm configuration. When receiving a JWT token, the middleware will pull the issuer from the iss claim and use it to lookup the appropriate algorithm in the middleware configuration to verify the JWT. (So, the iss claim is implicitly only "trusted" if verification succeeds.)
    • Optionally, you may include a :no-issuer key in the map of issuers - this value will be used if no iss claim is found in the incoming token.
  • :find-token-fn (optional): A single-argument function that will be used to pull the (encoded) token from the request map. If unspecified the token will be sought from the bearer token given in the Authorization header (i.e. an Authorization HTTP header of the form "Bearer TOKEN")
  • :reject-missing-token? (optional): A flag indicating whether a request missing a JWT token will be rejected with a 401 response. Default is true. If set to false a missing token will simply cause authentication to be skipped - although any authorization in your app will presumably fail as a result of no claims being found.

Configuring the cryptographic algorithms

Depending upon the cryptographic algorithm, a different map of options will be required. Note that, at the point your ring middleware is wired up, ring-jwt will throw an error if it detects that the given options are invalid.

Currently the following JWA algorithms are supported for the purposes of JWS:

AlgorithmOptions
ECDSA using P-256 and SHA-256{:alg :ES256 :public-key public-key} [1]
RSASSA-PKCS-v1_5 using SHA-256{:alg :RS256 :public-key public-key} [1]
{:alg :RS256 :jwk-endpoint "https://your/jwk/endpoint"} [2]
HMAC using SHA-256{:alg :HS256 :secret "your-secret"}
  • [1] public-key is of type java.security.PublicKey.
  • [2] Note that the content from that JWK endpoint is cached internally for up to 10 minutes using the Auth0 GuavaCachedJwkProvider.

Additionally, the following options are supported for all issuers:

  • leeway-seconds: The number of seconds leeway to give when verifying the expiry/active from claims of the token (i.e. the exp and nbf claims).

Other goodies

Keys for use with Integrant or Duct are available in kelveden/duct.middleware.ring-jwt.

Useful links

License

Distributed under the Eclipse Public License, the same as Clojure.

Can you improve this documentation? These fine people already did:
Alistair Dutton, Oliver Boyle, Jacek Schæ & Newton Beck
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close