Class: RackJwtVerifier::Verifier
- Inherits:
-
Object
- Object
- RackJwtVerifier::Verifier
- Defined in:
- lib/rack_jwt_verifier/verifier.rb
Overview
Decodes and verifies JWTs against key material from a configured source: a static PEM, a PEM served at a URL, a JWKS endpoint, or a shared HMAC secret. Handles caching, key rotation, claim enforcement and optional jti replay protection so the middleware does not have to.
Constant Summary collapse
- KeyFetchError =
Kept under the old constant so existing
rescue Verifier::KeyFetchErrorcode keeps working. RackJwtVerifier::KeyFetchError
- PUBLIC_KEY_CACHE_KEY =
Cache namespace for a fetched PEM; the full key also carries a digest of the URL.
KeySource::RemotePem::CACHE_KEY_PREFIX
- JWKS_CACHE_KEY =
Cache namespace for a fetched JWKS; the full key also carries a digest of the URL.
KeySource::RemoteJwks::CACHE_KEY_PREFIX
- CACHE_TTL_SECONDS =
The default TTL for cached key material (5 minutes)
KeySource::Remote::DEFAULT_CACHE_TTL
- DEFAULT_HTTP_TIMEOUT =
Default open/read timeout (seconds) for fetching key material
KeySource::Remote::DEFAULT_HTTP_TIMEOUT
- MAX_KEY_RESPONSE_BYTES =
Largest response body (bytes) accepted as key material
KeySource::Remote::MAX_RESPONSE_BYTES
- DEFAULT_REFETCH_INTERVAL =
Minimum gap (seconds) between rotation-triggered refetches
KeySource::Remote::DEFAULT_REFETCH_INTERVAL
- KEY_SOURCE_OPTIONS =
Exactly one of these tells the Verifier where its key comes from. Having shared_secret in the same exclusive set is what rules out "a secret next to a public key" — the classic RS256/HS256 confusion setup.
i[public_key public_key_url jwks_url shared_secret].freeze
- HMAC_ALGORITHMS =
The HMAC family, only ever enabled by shared_secret.
%w[HS256 HS384 HS512].freeze
- MIN_SECRET_BYTES =
RFC 7518 §3.2: an HMAC key must be at least as long as the hash output. Same numbers jwt_auth_client enforces on the signing side.
{ "HS256" => 32, "HS384" => 48, "HS512" => 64 }.freeze
- DEFAULT_ASYMMETRIC_ALGORITHMS =
Default accepted algorithms per key-source family.
%w[RS256].freeze
- DEFAULT_HMAC_ALGORITHMS =
%w[HS256].freeze
- CLAIM_VERIFY_FLAGS =
ruby-jwt only validates an expected claim value (e.g.
iss: "...") when the matchingverify_*flag is also set. Map each claim to its flag so we can switch the flag on automatically whenever a value is supplied. { iss: :verify_iss, aud: :verify_aud, sub: :verify_sub }.freeze
- DEFAULT_DECODE_OPTIONS =
Default options for JWT decoding to ensure strict security compliance. ruby-jwt only checks exp/nbf when the claim is present, so
expis also listed as required: a token with no expiry would otherwise be valid forever. { verify_expiration: true, verify_not_before: true, required_claims: %w[exp].freeze, leeway: 60 # Allow a 60-second clock skew for "exp" and "nbf" claims }.freeze
Instance Attribute Summary collapse
-
#algorithms ⇒ Array<String>
readonly
The algorithms this verifier accepts, after defaults and policy.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ Verifier
constructor
A new instance of Verifier.
-
#verify(token) ⇒ Hash
Decodes and verifies the JWT.
Constructor Details
#initialize(options = {}) ⇒ Verifier
Returns a new instance of Verifier.
86 87 88 89 90 91 92 |
# File 'lib/rack_jwt_verifier/verifier.rb', line 86 def initialize( = {}) source_name = key_source_name() @key_source = build_key_source(source_name, ) @algorithms = build_algorithms(source_name, ) = (.fetch(:decode_options, {}), replay: replay_wanted?()) @replay_guard = build_replay_guard(, [:leeway]) end |
Instance Attribute Details
#algorithms ⇒ Array<String> (readonly)
The algorithms this verifier accepts, after defaults and policy.
96 97 98 |
# File 'lib/rack_jwt_verifier/verifier.rb', line 96 def algorithms @algorithms end |
Instance Method Details
#verify(token) ⇒ Hash
Decodes and verifies the JWT.
104 105 106 107 108 109 110 |
# File 'lib/rack_jwt_verifier/verifier.rb', line 104 def verify(token) payload = decode_with_rotation(token) # Only a token that passed every other check is recorded: an expired or # mis-signed token must not be able to "burn" a jti. @replay_guard&.check!(payload) payload end |