Class: Verikloak::TokenDecoder
- Inherits:
-
Object
- Object
- Verikloak::TokenDecoder
- Defined in:
- lib/verikloak/token_decoder.rb
Overview
Verifies JWT tokens using a JWKs.
This class validates a JWT’s signature and standard claims (‘iss`, `aud`, `exp`, `nbf`, etc.) using the appropriate RSA public key selected by the JWT’s ‘kid` header. Only `RS256`-signed tokens with RSA JWKs are supported. It also supports a configurable clock skew (`leeway`) to account for minor time drift, which is applied uniformly to `exp`, `nbf`, and `iat` (Verikloak applies leeway to `iat` itself because ruby-jwt 3.x’s built-in ‘iat` validator ignores leeway).
Constant Summary collapse
- DEFAULT_LEEWAY =
Default clock skew tolerance in seconds.
60
Instance Method Summary collapse
-
#decode!(token) ⇒ Hash
Decodes and verifies a JWT.
-
#initialize(jwks:, issuer:, audience:, leeway: DEFAULT_LEEWAY, options: {}) ⇒ TokenDecoder
constructor
Initializes the decoder with a JWKs and verification criteria.
Constructor Details
#initialize(jwks:, issuer:, audience:, leeway: DEFAULT_LEEWAY, options: {}) ⇒ TokenDecoder
Initializes the decoder with a JWKs and verification criteria.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/verikloak/token_decoder.rb', line 38 def initialize(jwks:, issuer:, audience:, leeway: DEFAULT_LEEWAY, options: {}) @jwks = jwks @issuer = issuer @audience = audience # Keep backward compatibility; can be overridden by options[:leeway] @leeway = leeway # Normalize and store verification options @options = symbolize_keys( || {}) # Remove keys we manage ourselves so user-supplied values don't # re-enable ruby-jwt's built-in (broken w.r.t. leeway) iat validator # via the final merge in #jwt_decode_options. The user's intent for # :leeway / :verify_iat is still honoured by reading from @options # directly elsewhere in this class. @options_for_jwt = @options.except(:leeway, :verify_iat).freeze # Build a kid-indexed hash for O(1) JWK lookup @jwk_by_kid = {} Array(@jwks).each do |j| kid_key = fetch_indifferent(j, 'kid') @jwk_by_kid[kid_key] = j if kid_key end @options.freeze end |
Instance Method Details
#decode!(token) ⇒ Hash
Decodes and verifies a JWT.
74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/verikloak/token_decoder.rb', line 74 def decode!(token) with_error_handling do # Extract header without verifying signature (payload is ignored here). header = JWT.decode(token, nil, false).last validate_header(header) # check alg and kid present jwk = find_key_by_kid(header) # locate JWK by kid public_key = rsa_key_from_jwk(jwk) # import RSA public key payload = decode_with_public_key(token, public_key) # verify signature & claims payload end end |