class KeySet

KeySet takes a list of active key objects and supplies a method to find a key given it's ID.

Key objects should be hashes with at least the following structure: {

'kid': 'ID',
'n': 'modulus',
'e': 'exponent',

}

Attributes

keys[R]

Public Class Methods

new(keys:) click to toggle source
# File lib/omniauth/azure_adv2/key_set.rb, line 11
def initialize(keys:)
  @keys = keys
end

Public Instance Methods

find(key_id) click to toggle source
# File lib/omniauth/azure_adv2/key_set.rb, line 15
def find(key_id)
  key = find_key_or_raise_error(key_id)

  generate_public_key(
    modulus: decode_and_convert_to_number(key['n']),
    exponent: decode_and_convert_to_number(key['e']),
  )
end

Private Instance Methods

decode_and_convert_to_number(str) click to toggle source
# File lib/omniauth/azure_adv2/key_set.rb, line 38
def decode_and_convert_to_number(str)
  decoded = JWT.base64url_decode(str)

  decoded.unpack("C*").inject(0) { |sum, (byte, _)| sum * 256 + byte }
end
find_key_or_raise_error(id) click to toggle source
# File lib/omniauth/azure_adv2/key_set.rb, line 28
def find_key_or_raise_error(id)
  key = keys.find { |k| k['kid'] == id }

  if key.nil? || key.empty?
    fail JWT::VerificationError, 'No keys from key endpoint match the id token'
  end

  key
end
generate_public_key(modulus:, exponent:) click to toggle source
# File lib/omniauth/azure_adv2/key_set.rb, line 44
def generate_public_key(modulus:, exponent:)
  seq = OpenSSL::ASN1::Sequence.new([
    OpenSSL::ASN1::Integer.new(modulus),
    OpenSSL::ASN1::Integer.new(exponent),
  ])

  OpenSSL::PKey::RSA.new(seq.to_der)
end