diff --git a/keypairs.gemspec b/keypairs.gemspec index b8a6d72..3e46dad 100644 --- a/keypairs.gemspec +++ b/keypairs.gemspec @@ -39,6 +39,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rubocop-performance' # Linter for Performance optimization analysis spec.add_development_dependency 'rubocop-rails' # Linter for Rails-specific analysis spec.add_development_dependency 'shoulda-matchers' # RSpec matchers - spec.add_development_dependency 'sqlite3' # Database adapter + spec.add_development_dependency 'sqlite3', '~> 1.4' # Database adapter spec.add_development_dependency 'timecop' # Freeze time to test time-dependent code end diff --git a/lib/keypair.rb b/lib/keypair.rb index 38e19c0..1c6f117 100644 --- a/lib/keypair.rb +++ b/lib/keypair.rb @@ -34,7 +34,7 @@ # @attr [Time] not_before The time before which no payloads may be signed using the keypair. # @attr [Time] not_after The time after which no payloads may be signed using the keypair. # @attr [Time] expires_at The time after which the keypair may not be used for signature validation. -class Keypair < ActiveRecord::Base +class Keypair < ActiveRecord::Base # rubocop:disable Metrics/ClassLength ALGORITHM = 'RS256' ROTATION_INTERVAL = 1.month @@ -128,12 +128,15 @@ def self.jwt_encode_without_nonce(payload) # @raise [JWT::DecodeError] or any of it's subclasses if the decoding / validation fails. # @return [Hash] Decoded payload hash with indifferent access. def self.jwt_decode(id_token, options = {}) + decoding_keyset = Rails.cache.fetch('keypairs/Keypair/keyset_decode', expires_in: decode_cache_expires_in) do + keyset + end # Add default decoding options options.reverse_merge!( # Change the default algorithm to match the encoding algorithm algorithm: ALGORITHM, # Load our own keyset as valid keys - jwks: keyset, + jwks: decoding_keyset, # If the `sub` is provided, validate that it matches the payload `sub` verify_sub: true ) @@ -245,4 +248,11 @@ def secure_payload(payload, nonce: true) payload.reverse_merge!(secure_payload) end + + class << self + def decode_cache_expires_in + first_expires_at = valid.minimum(:expires_at) + first_expires_at ? first_expires_at - Time.zone.now : nil + end + end end diff --git a/lib/keypairs/version.rb b/lib/keypairs/version.rb index 1d26233..d354a9b 100644 --- a/lib/keypairs/version.rb +++ b/lib/keypairs/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Keypairs - VERSION = '2.0.0.develop' + VERSION = '1.3.4.develop' end diff --git a/spec/support/matchers/encrypt_attribute.rb b/spec/support/matchers/encrypt_attribute.rb index b046207..e0b823c 100644 --- a/spec/support/matchers/encrypt_attribute.rb +++ b/spec/support/matchers/encrypt_attribute.rb @@ -6,9 +6,9 @@ match do |model| # Correct responds to methods model.respond_to?(attribute) && - model.respond_to?("#{attribute}=") && + model.respond_to?(:"#{attribute}=") && model.respond_to?(database_column_name) && - model.respond_to?("#{database_column_name}=") && + model.respond_to?(:"#{database_column_name}=") && # Correct database columns model.class.column_names.exclude?(attribute.to_s) && model.class.column_names.include?(database_column_name)