Skip to content

Commit

Permalink
Revert "Support multiple relying parties (#296)"
Browse files Browse the repository at this point in the history
This reverts commit 2f54c92.
  • Loading branch information
grzuy committed Feb 28, 2021
1 parent 5e44214 commit dbff817
Show file tree
Hide file tree
Showing 20 changed files with 130 additions and 621 deletions.
14 changes: 5 additions & 9 deletions lib/webauthn/attestation_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,18 @@ module WebAuthn
class AttestationObject
extend Forwardable

def self.deserialize(attestation_object, relying_party)
from_map(CBOR.decode(attestation_object), relying_party)
def self.deserialize(attestation_object)
from_map(CBOR.decode(attestation_object))
end

def self.from_map(map, relying_party)
def self.from_map(map)
new(
authenticator_data: WebAuthn::AuthenticatorData.deserialize(map["authData"]),
attestation_statement: WebAuthn::AttestationStatement.from(
map["fmt"],
map["attStmt"],
relying_party: relying_party
)
attestation_statement: WebAuthn::AttestationStatement.from(map["fmt"], map["attStmt"])
)
end

attr_reader :authenticator_data, :attestation_statement, :relying_party
attr_reader :authenticator_data, :attestation_statement

def initialize(authenticator_data:, attestation_statement:)
@authenticator_data = authenticator_data
Expand Down
4 changes: 2 additions & 2 deletions lib/webauthn/attestation_statement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ class FormatNotSupportedError < Error; end
ATTESTATION_FORMAT_TPM => WebAuthn::AttestationStatement::TPM
}.freeze

def self.from(format, statement, relying_party: WebAuthn.configuration.relying_party)
def self.from(format, statement)
klass = FORMAT_TO_CLASS[format]

if klass
klass.new(statement, relying_party)
klass.new(statement)
else
raise(FormatNotSupportedError, "Unsupported attestation format '#{format}'")
end
Expand Down
17 changes: 10 additions & 7 deletions lib/webauthn/attestation_statement/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ class UnsupportedAlgorithm < Error; end
class Base
AAGUID_EXTENSION_OID = "1.3.6.1.4.1.45724.1.1.4"

def initialize(statement, relying_party = WebAuthn.configuration.relying_party)
def initialize(statement)
@statement = statement
@relying_party = relying_party
end

def valid?(_authenticator_data, _client_data_hash)
Expand All @@ -55,7 +54,7 @@ def attestation_certificate_key_id

private

attr_reader :statement, :relying_party
attr_reader :statement

def matching_aaguid?(attested_credential_data_aaguid)
extension = attestation_certificate&.extensions&.detect { |ext| ext.oid == AAGUID_EXTENSION_OID }
Expand Down Expand Up @@ -96,10 +95,10 @@ def attestation_trust_path

def trustworthy?(aaguid: nil, attestation_certificate_key_id: nil)
if ATTESTATION_TYPES_WITH_ROOT.include?(attestation_type)
relying_party.acceptable_attestation_types.include?(attestation_type) &&
configuration.acceptable_attestation_types.include?(attestation_type) &&
valid_certificate_chain?(aaguid: aaguid, attestation_certificate_key_id: attestation_certificate_key_id)
else
relying_party.acceptable_attestation_types.include?(attestation_type)
configuration.acceptable_attestation_types.include?(attestation_type)
end
end

Expand All @@ -123,7 +122,7 @@ def attestation_root_certificates_store(aaguid: nil, attestation_certificate_key

def root_certificates(aaguid: nil, attestation_certificate_key_id: nil)
root_certificates =
relying_party.attestation_root_certificates_finders.reduce([]) do |certs, finder|
configuration.attestation_root_certificates_finders.reduce([]) do |certs, finder|
if certs.empty?
finder.find(
attestation_format: format,
Expand Down Expand Up @@ -170,10 +169,14 @@ def verification_data(authenticator_data, client_data_hash)
def cose_algorithm
@cose_algorithm ||=
COSE::Algorithm.find(algorithm).tap do |alg|
alg && relying_party.algorithms.include?(alg.name) ||
alg && configuration.algorithms.include?(alg.name) ||
raise(UnsupportedAlgorithm, "Unsupported algorithm #{algorithm}")
end
end

def configuration
WebAuthn.configuration
end
end
end
end
7 changes: 3 additions & 4 deletions lib/webauthn/authenticator_assertion_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class SignatureVerificationError < VerificationError; end
class SignCountVerificationError < VerificationError; end

class AuthenticatorAssertionResponse < AuthenticatorResponse
def self.from_client(response, relying_party: WebAuthn.configuration.relying_party)
encoder = relying_party.encoder
def self.from_client(response)
encoder = WebAuthn.configuration.encoder

user_handle =
if response["userHandle"]
Expand All @@ -22,8 +22,7 @@ def self.from_client(response, relying_party: WebAuthn.configuration.relying_par
authenticator_data: encoder.decode(response["authenticatorData"]),
client_data_json: encoder.decode(response["clientDataJSON"]),
signature: encoder.decode(response["signature"]),
user_handle: user_handle,
relying_party: relying_party
user_handle: user_handle
)
end

Expand Down
17 changes: 7 additions & 10 deletions lib/webauthn/authenticator_attestation_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ class AttestedCredentialVerificationError < VerificationError; end
class AuthenticatorAttestationResponse < AuthenticatorResponse
extend Forwardable

def self.from_client(response, relying_party: WebAuthn.configuration.relying_party)
encoder = relying_party.encoder
def self.from_client(response)
encoder = WebAuthn.configuration.encoder

new(
attestation_object: encoder.decode(response["attestationObject"]),
client_data_json: encoder.decode(response["clientDataJSON"]),
relying_party: relying_party
client_data_json: encoder.decode(response["clientDataJSON"])
)
end

Expand All @@ -34,22 +33,21 @@ def initialize(attestation_object:, **options)
super(**options)

@attestation_object_bytes = attestation_object
@relying_party = relying_party
end

def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp_id: nil)
super

verify_item(:attested_credential)
if relying_party.verify_attestation_statement
if WebAuthn.configuration.verify_attestation_statement
verify_item(:attestation_statement)
end

true
end

def attestation_object
@attestation_object ||= WebAuthn::AttestationObject.deserialize(attestation_object_bytes, relying_party)
@attestation_object ||= WebAuthn::AttestationObject.deserialize(attestation_object_bytes)
end

def_delegators(
Expand All @@ -65,15 +63,14 @@ def attestation_object

private

attr_reader :attestation_object_bytes, :relying_party
attr_reader :attestation_object_bytes

def type
WebAuthn::TYPES[:create]
end

def valid_attested_credential?
attestation_object.valid_attested_credential? &&
relying_party.algorithms.include?(authenticator_data.credential.algorithm)
attestation_object.valid_attested_credential?
end

def valid_attestation_statement?
Expand Down
14 changes: 4 additions & 10 deletions lib/webauthn/authenticator_data/attested_credential_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AttestedCredentialData < BinData::Record

# TODO: use keyword_init when we dropped Ruby 2.4 support
Credential =
Struct.new(:id, :public_key, :algorithm) do
Struct.new(:id, :public_key) do
def public_key_object
COSE::Key.deserialize(public_key).to_pkey
end
Expand All @@ -47,7 +47,7 @@ def aaguid
def credential
@credential ||=
if valid?
Credential.new(id, public_key, algorithm)
Credential.new(id, public_key)
end
end

Expand All @@ -59,16 +59,10 @@ def length

private

def algorithm
COSE::Algorithm.find(cose_key.alg).name
end

def valid_credential_public_key?
!!cose_key.alg
end
cose_key = COSE::Key.deserialize(public_key)

def cose_key
@cose_key ||= COSE::Key.deserialize(public_key)
!!cose_key.alg && WebAuthn.configuration.algorithms.include?(COSE::Algorithm.find(cose_key.alg).name)
end

def public_key
Expand Down
11 changes: 5 additions & 6 deletions lib/webauthn/authenticator_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@ class UserPresenceVerificationError < VerificationError; end
class UserVerifiedVerificationError < VerificationError; end

class AuthenticatorResponse
def initialize(client_data_json:, relying_party: WebAuthn.configuration.relying_party)
def initialize(client_data_json:)
@client_data_json = client_data_json
@relying_party = relying_party
end

def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp_id: nil)
expected_origin ||= relying_party.origin || raise("Unspecified expected origin")
rp_id ||= relying_party.id
expected_origin ||= WebAuthn.configuration.origin || raise("Unspecified expected origin")
rp_id ||= WebAuthn.configuration.rp_id

verify_item(:type)
verify_item(:token_binding)
Expand All @@ -36,7 +35,7 @@ def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp
verify_item(:authenticator_data)
verify_item(:rp_id, rp_id || rp_id_from_origin(expected_origin))

if !relying_party.silent_authentication
if !WebAuthn.configuration.silent_authentication
verify_item(:user_presence)
end

Expand All @@ -59,7 +58,7 @@ def client_data

private

attr_reader :client_data_json, :relying_party
attr_reader :client_data_json

def verify_item(item, *args)
if send("valid_#{item}?", *args)
Expand Down
74 changes: 38 additions & 36 deletions lib/webauthn/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# frozen_string_literal: true

require 'forwardable'
require 'webauthn/relying_party'
require "openssl"
require "webauthn/encoder"
require "webauthn/error"

module WebAuthn
def self.configuration
Expand All @@ -12,49 +13,50 @@ def self.configure
yield(configuration)
end

class RootCertificateFinderNotSupportedError < Error; end

class Configuration
extend Forwardable

def_delegators :@relying_party,
:algorithms,
:algorithms=,
:encoding,
:encoding=,
:origin,
:origin=,
:verify_attestation_statement,
:verify_attestation_statement=,
:credential_options_timeout,
:credential_options_timeout=,
:silent_authentication,
:silent_authentication=,
:acceptable_attestation_types,
:acceptable_attestation_types=,
:attestation_root_certificates_finders,
:attestation_root_certificates_finders=,
:encoder,
:encoder=

attr_reader :relying_party
DEFAULT_ALGORITHMS = ["ES256", "PS256", "RS256"].compact.freeze

attr_accessor :algorithms
attr_accessor :encoding
attr_accessor :origin
attr_accessor :rp_id
attr_accessor :rp_name
attr_accessor :verify_attestation_statement
attr_accessor :credential_options_timeout
attr_accessor :silent_authentication
attr_accessor :acceptable_attestation_types
attr_reader :attestation_root_certificates_finders

def initialize
@relying_party = RelyingParty.new
@algorithms = DEFAULT_ALGORITHMS.dup
@encoding = WebAuthn::Encoder::STANDARD_ENCODING
@verify_attestation_statement = true
@credential_options_timeout = 120000
@silent_authentication = false
@acceptable_attestation_types = ['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA']
@attestation_root_certificates_finders = []
end

def rp_name
relying_party.name
# This is the user-data encoder.
# Used to decode user input and to encode data provided to the user.
def encoder
@encoder ||= WebAuthn::Encoder.new(encoding)
end

def rp_name=(name)
relying_party.name = name
end
def attestation_root_certificates_finders=(finders)
if !finders.respond_to?(:each)
finders = [finders]
end

def rp_id
relying_party.id
end
finders.each do |finder|
unless finder.respond_to?(:find)
raise RootCertificateFinderNotSupportedError, "Finder must implement `find` method"
end
end

def rp_id=(id)
relying_party.id = id
@attestation_root_certificates_finders = finders
end
end
end
9 changes: 4 additions & 5 deletions lib/webauthn/credential.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
require "webauthn/public_key_credential/request_options"
require "webauthn/public_key_credential_with_assertion"
require "webauthn/public_key_credential_with_attestation"
require "webauthn/relying_party"

module WebAuthn
module Credential
Expand All @@ -16,12 +15,12 @@ def self.options_for_get(**keyword_arguments)
WebAuthn::PublicKeyCredential::RequestOptions.new(**keyword_arguments)
end

def self.from_create(credential, relying_party: WebAuthn.configuration.relying_party)
WebAuthn::PublicKeyCredentialWithAttestation.from_client(credential, relying_party: relying_party)
def self.from_create(credential)
WebAuthn::PublicKeyCredentialWithAttestation.from_client(credential)
end

def self.from_get(credential, relying_party: WebAuthn.configuration.relying_party)
WebAuthn::PublicKeyCredentialWithAssertion.from_client(credential, relying_party: relying_party)
def self.from_get(credential)
WebAuthn::PublicKeyCredentialWithAssertion.from_client(credential)
end
end
end
4 changes: 2 additions & 2 deletions lib/webauthn/fake_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module WebAuthn
class FakeClient
TYPES = { create: "webauthn.create", get: "webauthn.get" }.freeze

attr_reader :origin, :token_binding, :encoding
attr_reader :origin, :token_binding

def initialize(
origin = fake_origin,
Expand Down Expand Up @@ -105,7 +105,7 @@ def get(challenge: fake_challenge,

private

attr_reader :authenticator
attr_reader :authenticator, :encoding

def data_json_for(method, challenge)
data = {
Expand Down
Loading

0 comments on commit dbff817

Please sign in to comment.