Class: Clarion::Authenticator
- Inherits:
-
Object
- Object
- Clarion::Authenticator
- Defined in:
- lib/clarion/authenticator.rb
Defined Under Namespace
Classes: Error, InvalidAssertion, InvalidKey
Instance Attribute Summary collapse
-
#authn ⇒ Object
readonly
Returns the value of attribute authn.
-
#counter ⇒ Object
readonly
Returns the value of attribute counter.
-
#legacy_app_id ⇒ Object
readonly
Returns the value of attribute legacy_app_id.
-
#rp_id ⇒ Object
readonly
Returns the value of attribute rp_id.
-
#store ⇒ Object
readonly
Returns the value of attribute store.
Instance Method Summary collapse
- #challenge ⇒ Object
- #credential_request_options ⇒ Object
-
#initialize(authn, counter, store, rp_id: nil, legacy_app_id: nil) ⇒ Authenticator
constructor
A new instance of Authenticator.
- #verify!(challenge: self.challenge(), origin:, extension_results: {}, credential_id:, authenticator_data:, client_data_json:, signature:) ⇒ Object
- #webauthn_request_extensions ⇒ Object
Constructor Details
#initialize(authn, counter, store, rp_id: nil, legacy_app_id: nil) ⇒ Authenticator
Returns a new instance of Authenticator.
12 13 14 15 16 17 18 |
# File 'lib/clarion/authenticator.rb', line 12 def initialize(authn, counter, store, rp_id: nil, legacy_app_id: nil) @authn = authn @counter = counter @store = store @rp_id = rp_id @legacy_app_id = legacy_app_id end |
Instance Attribute Details
#authn ⇒ Object (readonly)
Returns the value of attribute authn.
20 21 22 |
# File 'lib/clarion/authenticator.rb', line 20 def authn @authn end |
#counter ⇒ Object (readonly)
Returns the value of attribute counter.
20 21 22 |
# File 'lib/clarion/authenticator.rb', line 20 def counter @counter end |
#legacy_app_id ⇒ Object (readonly)
Returns the value of attribute legacy_app_id.
20 21 22 |
# File 'lib/clarion/authenticator.rb', line 20 def legacy_app_id @legacy_app_id end |
#rp_id ⇒ Object (readonly)
Returns the value of attribute rp_id.
20 21 22 |
# File 'lib/clarion/authenticator.rb', line 20 def rp_id @rp_id end |
#store ⇒ Object (readonly)
Returns the value of attribute store.
20 21 22 |
# File 'lib/clarion/authenticator.rb', line 20 def store @store end |
Instance Method Details
#challenge ⇒ Object
22 23 24 |
# File 'lib/clarion/authenticator.rb', line 22 def challenge @challenge ||= SecureRandom.random_bytes(32) end |
#credential_request_options ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/clarion/authenticator.rb', line 32 def { publicKey: { timeout: 60000, # Convert to ArrayBuffer in sign.js challenge: challenge.each_byte.map(&:ord), allowCredentials: authn.keys.map { |_| {type: 'public-key', id: Base64.urlsafe_decode64(_.handle).each_byte.map(&:ord)} }, extensions: webauthn_request_extensions, } } end |
#verify!(challenge: self.challenge(), origin:, extension_results: {}, credential_id:, authenticator_data:, client_data_json:, signature:) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/clarion/authenticator.rb', line 44 def verify!(challenge: self.challenge(), origin:, extension_results: {}, credential_id:, authenticator_data:, client_data_json:, signature:) assertion = WebAuthn::AuthenticatorAssertionResponse.new( credential_id: credential_id, authenticator_data: authenticator_data, client_data_json: client_data_json, signature: signature, ) key = authn.verify_by_handle(credential_id) unless key raise Authenticator::InvalidKey end rp_id = extension_results&.fetch('appid', extension_results&.fetch(:appid, false)) ? legacy_app_id : self.rp_id() allowed_credentials = authn.keys.map { |_| {id: _.handle, public_key: _.public_key_bytes} } unless assertion.valid?(challenge, origin, rp_id: rp_id, allowed_credentials: allowed_credentials) raise Authenticator::InvalidAssertion, "invalid assertion" end sign_count = assertion.authenticator_data.sign_count last_sign_count = counter ? counter.get(key) : 0 if sign_count <= last_sign_count raise Authenticator::InvalidAssertion, "sign_count is decreased" end key.counter = sign_count counter.store(key) if counter store.store_authn(authn) true end |
#webauthn_request_extensions ⇒ Object
26 27 28 29 30 |
# File 'lib/clarion/authenticator.rb', line 26 def webauthn_request_extensions {}.tap do |e| e[:appid] = legacy_app_id if legacy_app_id end end |