class Fridge::AccessToken
Attributes
actor[RW]
attributes[RW]
expires_at[RW]
id[RW]
issuer[RW]
jwt[RW]
scope[RW]
subject[RW]
Public Class Methods
new(jwt_or_options = nil)
click to toggle source
# File lib/fridge/access_token.rb, line 8 def initialize(jwt_or_options = nil) options = case jwt_or_options when String self.jwt = jwt_or_options validate_public_key! decode_and_verify(jwt_or_options) when Hash then jwt_or_options else {} end [:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key| send "#{key}=", options.delete(key) end self.attributes = options end
Public Instance Methods
algorithm()
click to toggle source
# File lib/fridge/access_token.rb, line 87 def algorithm config.signing_algorithm end
config()
click to toggle source
# File lib/fridge/access_token.rb, line 91 def config Fridge.configuration end
decode_and_verify(jwt)
click to toggle source
# File lib/fridge/access_token.rb, line 48 def decode_and_verify(jwt) payload, _header = JWT.decode(jwt, public_key, true, algorithm: algorithm) decode_from_jwt(payload) rescue JWT::ExpiredSignature => e raise ExpiredToken, e.message rescue JWT::DecodeError => e raise InvalidToken, e.message end
downgrade()
click to toggle source
# File lib/fridge/access_token.rb, line 57 def downgrade self.scope = 'read' end
encode_and_sign()
click to toggle source
# File lib/fridge/access_token.rb, line 36 def encode_and_sign h = {} [:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key| h[key] = send(key) end h.merge!(attributes) h = encode_for_jwt(h) JWT.encode(h, private_key, algorithm) rescue StandardError raise SerializationError, 'Invalid private key or signing algorithm' end
expired?()
click to toggle source
# File lib/fridge/access_token.rb, line 65 def expired? expires_at.nil? || expires_at < Time.now end
private_key()
click to toggle source
# File lib/fridge/access_token.rb, line 69 def private_key return unless config.private_key @private_key ||= OpenSSL::PKey::RSA.new(config.private_key) rescue StandardError nil end
public_key()
click to toggle source
# File lib/fridge/access_token.rb, line 77 def public_key if config.private_key @public_key ||= OpenSSL::PKey::RSA.new(config.private_key).public_key elsif config.public_key @public_key ||= OpenSSL::PKey::RSA.new(config.public_key) end rescue StandardError nil end
serialize()
click to toggle source
# File lib/fridge/access_token.rb, line 28 def serialize return jwt if jwt validate_parameters! validate_private_key! encode_and_sign end
to_s()
click to toggle source
# File lib/fridge/access_token.rb, line 24 def to_s serialize end
valid?()
click to toggle source
# File lib/fridge/access_token.rb, line 61 def valid? !expired? end
Protected Instance Methods
decode_from_jwt(hash)
click to toggle source
# File lib/fridge/access_token.rb, line 152 def decode_from_jwt(hash) hash = hash.dup out = { id: hash.delete('id'), issuer: hash.delete('iss'), subject: hash.delete('sub'), scope: hash.delete('scope') }.delete_if { |_, v| v.nil? } hash.delete('exp').tap { |e| out[:expires_at] = Time.at(e) if e } hash.delete('act').tap { |a| out[:actor] = decode_from_jwt(a) if a } # Extra attributes hash.delete_if { |_, v| v.nil? } hash = Hash[hash.map { |k, v| [k.to_sym, v] }] out.merge!(hash) out end
encode_for_jwt(hash)
click to toggle source
Internally, we use “subject” to refer to “sub”, and so on. We also represent some objects (expiry) differently. These functions do the mapping from Fridge
to JWT and vice-versa.
# File lib/fridge/access_token.rb, line 129 def encode_for_jwt(hash) hash = hash.dup out = { id: hash.delete(:id), iss: hash.delete(:issuer), sub: hash.delete(:subject), scope: hash.delete(:scope) }.delete_if { |_, v| v.nil? } # Unfortunately, nil.to_i returns 0, which means we can't # easily clean out exp if we include it although it wasn't passed # in like we do for other keys. So, we only include it if it's # actually passed in and non-nil. Either way, we delete the keys. hash.delete(:expires_at).tap { |e| out[:exp] = e.to_i if e } hash.delete(:actor).tap { |a| out[:act] = encode_for_jwt(a) if a } # Extra attributes passed through as-is out.merge!(hash) out end
method_missing(method, *args, &block)
click to toggle source
Calls superclass method
# File lib/fridge/access_token.rb, line 97 def method_missing(method, *args, &block) if attributes.key?(method) attributes[method] else super end end
respond_to_missing?(method, include_private = false)
click to toggle source
Calls superclass method
# File lib/fridge/access_token.rb, line 105 def respond_to_missing?(method, include_private = false) attributes.key?(method) || super end
validate_parameters!()
click to toggle source
# File lib/fridge/access_token.rb, line 109 def validate_parameters! [:subject, :expires_at].each do |attribute| next if send(attribute) raise SerializationError, "Missing attribute: #{attribute}" end end
validate_private_key!()
click to toggle source
# File lib/fridge/access_token.rb, line 117 def validate_private_key! raise SerializationError, 'No private key configured' unless private_key end
validate_public_key!()
click to toggle source
# File lib/fridge/access_token.rb, line 121 def validate_public_key! raise SerializationError, 'No public key configured' unless public_key end