Skip to content

Commit

Permalink
fix: Cache keyset for decoding
Browse files Browse the repository at this point in the history
Cache keyset for decoding
  • Loading branch information
KoenSengers committed Aug 2, 2024
1 parent b078859 commit cb680f6
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 6 deletions.
2 changes: 1 addition & 1 deletion keypairs.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 17 additions & 2 deletions lib/keypair.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -133,13 +133,28 @@ def self.jwt_decode(id_token, options = {})
# Change the default algorithm to match the encoding algorithm
algorithm: ALGORITHM,
# Load our own keyset as valid keys
jwks: keyset,
jwks: jwk_loader_cached,
# If the `sub` is provided, validate that it matches the payload `sub`
verify_sub: true
)
JWT.decode(id_token, nil, true, options).first.with_indifferent_access
end

# options[:invalidate] will be `true` if a matching `kid` was not found
# https://github.com/jwt/ruby-jwt/blob/master/lib/jwt/jwk/key_finder.rb#L31
def self.jwk_loader_cached
->(options) do
cached_jwks(force: options[:invalidate]) || {}
end
end


def self.cached_jwks(force: false)
Rails.cache.fetch('keypairs/Keypair/jwks', force: force, skip_nil: true) do
keyset
end
end

# JWT encodes the payload with this keypair.
# It automatically adds the security attributes +iat+, +exp+ and +nonce+ to the payload.
# It automatically sets the +kid+ in the header.
Expand Down
2 changes: 1 addition & 1 deletion lib/keypairs/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Keypairs
VERSION = '2.0.0.develop'
VERSION = '1.3.4.develop'
end
4 changes: 2 additions & 2 deletions spec/support/matchers/encrypt_attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit cb680f6

Please sign in to comment.