Hello Auth0 Community,
I have implemented JWT verification in my application by following the Auth0 documentation. After further reading on how to locate JSON Web Key Sets, I decided to enhance the efficiency of the process by implementing caching. This way, I avoid performing an HTTP request to Auth0 for each token verification.
Here’s the code snippet I’m using for caching the JWKS:
# frozen_string_literal: true
require "net/http"
require "uri"
class JsonWebToken
TOKEN_ISSUER = ENV.fetch("AUTH0_TOKEN_ISSUER").chomp("/").concat("/")
AUDIENCE = ENV.fetch("AUTH0_AUDIENCE")
JWKS_CACHE_EXPIRE_IN = 2.hours
def self.verify(token, retrying: false)
JWT.decode(
token,
nil,
true, # Verify the signature of this token
algorithms: "RS256",
iss: TOKEN_ISSUER,
verify_iss: true,
aud: AUDIENCE,
verify_aud: true
) do |header|
jwks_hash[header["kid"]]
end
rescue JWT::DecodeError => e
raise if retrying
Rails.cache.delete("jwks_keys")
verify(token, retrying: true)
end
def self.jwks_hash(force_update = false)
Rails.cache.fetch("jwks_keys", force: force_update, expires_in: JWKS_CACHE_EXPIRE_IN) do
jwks_raw = Net::HTTP.get URI("#{TOKEN_ISSUER}.well-known/jwks.json")
jwks_keys = Array(JSON.parse(jwks_raw)["keys"])
jwks_keys.map do |key|
[
key["kid"],
OpenSSL::X509::Certificate.new(
Base64.decode64(key["x5c"].first)
).public_key
]
end.to_h
end
end
end
I would greatly appreciate any feedback on this implementation:
- Is this implementation correct and secure according to best practices?
- What is the recommended expiration time for caching the JWKS?
- Are there any other recommendations or best practices I might have missed?
Thank you for your time and assistance!