class WebAuthn::AuthenticatorResponse
def client_data
def client_data @client_data ||= WebAuthn::ClientData.new(client_data_json) end
def initialize(client_data_json:, relying_party: WebAuthn.configuration.relying_party)
def initialize(client_data_json:, relying_party: WebAuthn.configuration.relying_party) @client_data_json = client_data_json @relying_party = relying_party end
def rp_id_from_origin(expected_origin)
def rp_id_from_origin(expected_origin) URI.parse(expected_origin).host end
def type
def type raise NotImplementedError, "Please define #type method in subclass" end
def valid?(*args, **keyword_arguments)
def valid?(*args, **keyword_arguments) verify(*args, **keyword_arguments) rescue WebAuthn::VerificationError false end
def valid_authenticator_data?
def valid_authenticator_data? authenticator_data.valid? rescue WebAuthn::AuthenticatorDataFormatError false end
def valid_challenge?(expected_challenge)
def valid_challenge?(expected_challenge) OpenSSL.secure_compare(client_data.challenge, expected_challenge) end
def valid_origin?(expected_origin)
def valid_origin?(expected_origin) expected_origin && (client_data.origin == expected_origin) end
def valid_rp_id?(rp_id)
def valid_rp_id?(rp_id) OpenSSL::Digest::SHA256.digest(rp_id) == authenticator_data.rp_id_hash end
def valid_token_binding?
def valid_token_binding? client_data.valid_token_binding_format? end
def valid_type?
def valid_type? client_data.type == type end
def valid_user_presence?
def valid_user_presence? authenticator_data.user_flagged? end
def valid_user_verified?
def valid_user_verified? authenticator_data.user_verified? end
def verify(expected_challenge, expected_origin = nil, user_presence: nil, user_verification: nil, rp_id: nil)
def verify(expected_challenge, expected_origin = nil, user_presence: nil, user_verification: nil, rp_id: nil) expected_origin ||= relying_party.origin || raise("Unspecified expected origin") rp_id ||= relying_party.id verify_item(:type) verify_item(:token_binding) verify_item(:challenge, expected_challenge) verify_item(:origin, expected_origin) verify_item(:authenticator_data) verify_item(:rp_id, rp_id || rp_id_from_origin(expected_origin)) # Fallback to RP configuration unless user_presence is passed in explicitely if user_presence.nil? && !relying_party.silent_authentication || user_presence verify_item(:user_presence) end if user_verification verify_item(:user_verified) end true end
def verify_item(item, *args)
def verify_item(item, *args) if send("valid_#{item}?", *args) true else camelized_item = item.to_s.split('_').map { |w| w.capitalize }.join error_const_name = "WebAuthn::#{camelized_item}VerificationError" raise Object.const_get(error_const_name) end end