Files
fizzy/lib/action_pack/web_authn/authenticator/attestation.rb
T
Stanko K.R. 017bcc9ce1 Polish up Passkey interface
- Fix indentation
- Split awkward initializer into separate methods
- Rename credentials to passkeys
- Simplify authenticator registry loading
- Flatten nested errors under ActionPack::WebAuthn
- Set passkey current params only requests that use it
- Inline anemic methods
- Replace custom validation with ActiveModel::Validation
- Rename identity to holder in Passkey
- Rename credentials to passkeys in JS
- Extract framework library out of controllers
- Pass params hashes down to ActionPack
- Attempt to simplify public interface
- Push data decoding down to the classes representing the data
- Introduce has_passkeys
- Add CBOR bigint support
- Rename ActionPack::WebAuthn::Passkey to ActionPack::Passkey
- Add create_passkey_button helper
- Rename public-key to creation-options
- Add sign_in_with_passkey_button helper
- Dispatch events for the whole Passkey lifecycle
- Add ED25519 support
- Prevent crash on missing meta tag
- Validate resident key options
- Don't clobber existing ActionPack config options
- Validate cryptographic params
- Move CurrentWebAuthnRequest into ActionPack::Passkey
- Use ActiveModel::Attributes for Options objects
- Implement expiring challanges
- Add lifecycle events
- Extract param helpers into Request
- Add passkey_creation_options and passkey_request_options helpers
- Add create_passkey_challenge to make it easier to override the create method if needed
- Prefix all view helpers with passkey_
- Auto-include ActionPack::Passkey::Holder
- Make the passkey challange url configurable
- Add a reminder about Passkeys to the magic link email
2026-03-18 11:51:10 +01:00

74 lines
2.4 KiB
Ruby

# = Action Pack WebAuthn Attestation
#
# Decodes and represents the attestation object returned by an authenticator
# during registration. The attestation object is CBOR-encoded and contains
# the authenticator data along with an optional attestation statement.
#
# == Usage
#
# attestation = ActionPack::WebAuthn::Authenticator::Attestation.decode(
# attestation_object_bytes
# )
#
# attestation.credential_id # => "abc123..."
# attestation.public_key # => OpenSSL::PKey::EC
# attestation.sign_count # => 0
#
# == Attributes
#
# [+authenticator_data+]
# The parsed Data containing credential information.
#
# [+format+]
# The attestation statement format (e.g., "none", "packed", "fido-u2f").
#
# [+attestation_statement+]
# The attestation statement, which may contain a signature from the
# authenticator manufacturer. Empty for "none" format.
#
# == Delegated Methods
#
# The following methods are delegated to +authenticator_data+:
#
# * +credential_id+ - Base64URL-encoded credential identifier
# * +public_key+ - OpenSSL public key object
# * +public_key_bytes+ - Raw COSE key bytes
# * +sign_count+ - Signature counter for replay detection
#
class ActionPack::WebAuthn::Authenticator::Attestation
attr_reader :authenticator_data, :format, :attestation_statement
delegate :credential_id, :public_key, :public_key_bytes, :sign_count, :aaguid, :backed_up?, to: :authenticator_data
# Wraps raw attestation data into an Attestation instance. Accepts an
# existing Attestation object (returned as-is), a Base64URL-encoded string,
# or raw binary.
def self.wrap(data)
if data.is_a?(self)
data
else
data = Base64.urlsafe_decode64(data) unless data.encoding == Encoding::BINARY
decode(data)
end
rescue ArgumentError
raise ActionPack::WebAuthn::InvalidResponseError, "Invalid base64 encoding in attestation object"
end
# Decodes a CBOR-encoded attestation object into an Attestation instance.
def self.decode(bytes)
cbor = ActionPack::WebAuthn::CborDecoder.decode(bytes)
new(
authenticator_data: ActionPack::WebAuthn::Authenticator::Data.decode(cbor["authData"]),
format: cbor["fmt"],
attestation_statement: cbor["attStmt"]
)
end
def initialize(authenticator_data:, format:, attestation_statement:)
@authenticator_data = authenticator_data
@format = format
@attestation_statement = attestation_statement
end
end