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