Files
gamertan bfe6cfd29e
verify / verify (push) Successful in 3m40s
auth: publish passkey foundations preview
2026-08-21 17:33:00 -04:00

1323 lines
56 KiB
Go

package metadata
import (
"crypto/x509"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/google/uuid"
)
// Fetch creates a new HTTP client and gets the production metadata, decodes it, and parses it. This is an
// instrumentation simplification that makes it easier to either just grab the latest metadata or for implementers to
// see the rough process of retrieving it to implement any of their own logic.
func Fetch() (metadata *Metadata, err error) {
var (
decoder *Decoder
payload *PayloadJSON
resp *http.Response
)
client := &http.Client{}
if resp, err = client.Get(ProductionMDSURL); err != nil {
return nil, err
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("error occurred fetching metadata: status code %d", resp.StatusCode)
}
if decoder, err = NewDecoder(WithIgnoreEntryParsingErrors()); err != nil {
return nil, err
}
if payload, err = decoder.Decode(resp.Body); err != nil {
return nil, err
}
return decoder.Parse(payload)
}
// Metadata represents a FIDO Metadata Service BLOB in either a fully parsed or partially parsed state.
type Metadata struct {
// Parsed contains the successfully parsed BLOB payload entries.
Parsed Parsed
// Unparsed contains entries that failed to parse, along with their errors.
Unparsed []EntryError
}
func (m *Metadata) ToMap() (metadata map[uuid.UUID]*Entry) {
metadata = make(map[uuid.UUID]*Entry)
for _, entry := range m.Parsed.Entries {
if entry.AaGUID != uuid.Nil {
metadata[entry.AaGUID] = &entry
}
}
return metadata
}
// Parsed is a structure representing the Metadata BLOB Payload dictionary.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-mds-blob-payload
type Parsed struct {
// The legalHeader, which MUST be in each BLOB, is an indication of the acceptance of the relevant legal agreement
// for using the MDS.
LegalHeader string
// The serial number of this Metadata BLOB Payload. This serial number MUST be incremented whenever the contents
// of the BLOB changes. Serial numbers MUST be consecutive and strictly monotonic, i.e. the successor BLOB will
// have a no value exactly incremented by one.
Number int
// ISO-8601 formatted date when the next update will be provided at latest. The use of this field is discouraged
// and may be removed in a future version of the spec.
NextUpdate time.Time
// List of zero or more MetadataBLOBPayloadEntry objects.
Entries []Entry
}
// PayloadJSON is an intermediary JSON/JWT representation of the Metadata BLOB Payload dictionary and the JSON
// representation of the [Parsed] struct.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-mds-blob-payload
type PayloadJSON struct {
// LegalHeader is an indication of the acceptance of the relevant legal agreement for using the MDS.
LegalHeader string `json:"legalHeader"`
// Number is the serial number of this Metadata BLOB Payload.
Number int `json:"no"`
// NextUpdate is an ISO-8601 formatted date when the next update will be provided at latest.
NextUpdate string `json:"nextUpdate"`
// Entries is a list of zero or more MetadataBLOBPayloadEntry objects.
Entries []EntryJSON `json:"entries"`
}
func (j PayloadJSON) Parse() (payload Parsed, err error) {
var update time.Time
if update, err = time.Parse(time.DateOnly, j.NextUpdate); err != nil {
return payload, fmt.Errorf("error occurred parsing next update value '%s': %w", j.NextUpdate, err)
}
n := len(j.Entries)
entries := make([]Entry, n)
for i := 0; i < n; i++ {
if entries[i], err = j.Entries[i].Parse(); err != nil {
return payload, fmt.Errorf("error occurred parsing entry %d: %w", i, err)
}
}
return Parsed{
LegalHeader: j.LegalHeader,
Number: j.Number,
NextUpdate: update,
Entries: entries,
}, nil
}
// Entry is a structure representing the Metadata BLOB Payload Entry dictionary.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-mds-blob-pe
type Entry struct {
// Aaid is the AAID of the authenticator this metadata BLOB payload entry relates to. This field MUST be set if
// the authenticator implements FIDO UAF.
Aaid string
// AaGUID is the Authenticator Attestation GUID. This field MUST be set if the authenticator implements FIDO2.
AaGUID uuid.UUID
// AttestationCertificateKeyIdentifiers is a list of the attestation certificate public key identifiers encoded as
// hex string. This field MUST be set if neither aaid nor aaguid are set.
AttestationCertificateKeyIdentifiers []string
// MetadataStatement is the metadataStatement JSON object as defined in FIDOMetadataStatement.
MetadataStatement Statement
// BiometricStatusReports is the status of the FIDO Biometric Certification of one or more biometric components of
// the Authenticator.
BiometricStatusReports []BiometricStatusReport
// StatusReports is an array of status reports applicable to this authenticator.
StatusReports []StatusReport
// TimeOfLastStatusChange is an ISO-8601 formatted date since when the status report array was set to the current
// value.
TimeOfLastStatusChange time.Time
// RogueListURL is a URL of a list of rogue (i.e. untrusted) individual authenticators.
RogueListURL *url.URL
// RogueListHash is the hash value computed over the Base64url encoding of the UTF-8 representation of the JSON
// encoded rogueList available at rogueListURL (with type rogueListEntry[]). This hash value MUST be present and
// non-empty whenever rogueListURL is present.
RogueListHash string
}
// EntryJSON is an intermediary JSON/JWT structure representing the Metadata BLOB Payload Entry dictionary and
// the JSON representation of the [Entry] struct.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-mds-blob-pe
type EntryJSON struct {
// Aaid is the AAID of the authenticator. Set if the authenticator implements FIDO UAF.
Aaid string `json:"aaid"`
// AaGUID is the Authenticator Attestation GUID. Set if the authenticator implements FIDO2.
AaGUID string `json:"aaguid"`
// AttestationCertificateKeyIdentifiers is a list of attestation certificate public key identifiers (hex).
AttestationCertificateKeyIdentifiers []string `json:"attestationCertificateKeyIdentifiers"`
// MetadataStatement is the metadataStatement JSON object as defined in FIDOMetadataStatement.
MetadataStatement StatementJSON `json:"metadataStatement"`
// BiometricStatusReports is the biometric certification status of one or more biometric components.
BiometricStatusReports []BiometricStatusReportJSON `json:"biometricStatusReports"`
// StatusReports is an array of status reports applicable to this authenticator.
StatusReports []StatusReportJSON `json:"statusReports"`
// TimeOfLastStatusChange is an ISO-8601 formatted date since when the status report array was set.
TimeOfLastStatusChange string `json:"timeOfLastStatusChange"`
// RogueListURL is a URL of a list of rogue (i.e. untrusted) individual authenticators.
RogueListURL string `json:"rogueListURL"`
// RogueListHash is the hash value computed over the Base64url encoding of the rogueList at rogueListURL.
RogueListHash string `json:"rogueListHash"`
}
func (j EntryJSON) Parse() (entry Entry, err error) {
var aaguid uuid.UUID
if len(j.AaGUID) != 0 {
if aaguid, err = uuid.Parse(j.AaGUID); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error parsing AAGUID: %w", j.AaGUID, err)
}
}
var statement Statement
if statement, err = j.MetadataStatement.Parse(); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': %w", j.AaGUID, err)
}
var i, n int
n = len(j.BiometricStatusReports)
bsrs := make([]BiometricStatusReport, n)
for i = 0; i < n; i++ {
if bsrs[i], err = j.BiometricStatusReports[i].Parse(); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error occurred parsing biometric status report %d: %w", j.AaGUID, i, err)
}
}
n = len(j.StatusReports)
srs := make([]StatusReport, n)
for i = 0; i < n; i++ {
if srs[i], err = j.StatusReports[i].Parse(); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error occurred parsing status report %d: %w", j.AaGUID, i, err)
}
}
var change time.Time
if change, err = time.Parse(time.DateOnly, j.TimeOfLastStatusChange); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error occurred parsing time of last status change value: %w", j.AaGUID, err)
}
var rogues *url.URL
if len(j.RogueListURL) != 0 {
if rogues, err = url.ParseRequestURI(j.RogueListURL); err != nil {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error occurred parsing rogue list URL value: %w", j.AaGUID, err)
}
if len(j.RogueListHash) == 0 {
return entry, fmt.Errorf("error occurred parsing metadata entry with AAGUID '%s': error occurred validating rogue list URL value: the rogue list hash was absent", j.AaGUID)
}
}
return Entry{
Aaid: j.Aaid,
AaGUID: aaguid,
AttestationCertificateKeyIdentifiers: j.AttestationCertificateKeyIdentifiers,
MetadataStatement: statement,
BiometricStatusReports: bsrs,
StatusReports: srs,
TimeOfLastStatusChange: change,
RogueListURL: rogues,
RogueListHash: j.RogueListHash,
}, nil
}
// Statement is a structure representing the Metadata Statement dictionary. Authenticator metadata statements are used
// directly by the FIDO server at a relying party, but the information contained in the authoritative statement is used
// in several other places.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-md-keys
type Statement struct {
// The LegalHeader, if present, contains a legal guide for accessing and using metadata, which itself MAY contain
// URL(s) pointing to further information, such as a full Terms and Conditions statement.
LegalHeader string
// Aaid is the Authenticator Attestation ID.
Aaid string
// AaGUID is the Authenticator Attestation GUID.
AaGUID uuid.UUID
// AttestationCertificateKeyIdentifiers is a list of the attestation certificate public key identifiers encoded as
// hex string.
AttestationCertificateKeyIdentifiers []string
// FriendlyNames contains friendly names (i.e., public trade name) of the authenticator in multiple languages.
FriendlyNames map[string]string
// Description is a human-readable, short description of the authenticator, in English.
Description string
// AlternativeDescriptions is a list of human-readable short descriptions of the authenticator in different
// languages.
AlternativeDescriptions map[string]string
// AuthenticatorVersion is the earliest (i.e. lowest) trustworthy authenticatorVersion meeting the requirements
// specified in this metadata statement.
AuthenticatorVersion uint32
// ProtocolFamily is the FIDO protocol family. The values "uaf", "u2f", and "fido2" are supported.
ProtocolFamily string
// Schema is the Metadata Schema version.
Schema uint16
// Upv is the FIDO unified protocol version(s) (related to the specific protocol family) supported by this
// authenticator.
Upv []Version
// AuthenticationAlgorithms is the list of authentication algorithms supported by the authenticator.
AuthenticationAlgorithms []AuthenticationAlgorithm
// PublicKeyAlgAndEncodings is the list of public key formats supported by the authenticator during registration
// operations.
PublicKeyAlgAndEncodings []PublicKeyAlgAndEncoding
// AttestationTypes is the supported attestation type(s).
AttestationTypes AuthenticatorAttestationTypes
// UserVerificationDetails is a list of alternative VerificationMethodANDCombinations.
UserVerificationDetails [][]VerificationMethodDescriptor
// KeyProtection is a 16-bit number representing the bit fields defined by the KEY_PROTECTION constants in the FIDO
// Registry of Predefined Values.
KeyProtection []string
// IsKeyRestricted is set to true or it is omitted, if the Uauth private key is restricted by the authenticator to
// only sign valid FIDO signature assertions. This entry is set to false, if the authenticator doesn't restrict the
// Uauth key to only sign valid FIDO signature assertions.
IsKeyRestricted bool
// IsFreshUserVerificationRequired is set to true or it is omitted, if Uauth key usage always requires a fresh user
// verification. This entry is set to false, if the Uauth key can be used without requiring a fresh user
// verification, i.e. without any additional user interaction, if the user was verified a (potentially configurable)
// caching time ago.
IsFreshUserVerificationRequired bool
// MatcherProtection is a 16-bit number representing the bit fields defined by the MATCHER_PROTECTION constants in
// the FIDO Registry of Predefined Values.
MatcherProtection []string
// CryptoStrength is the authenticator's overall claimed cryptographic strength in bits (sometimes also called
// security strength or security level).
CryptoStrength uint16
// AttachmentHint is a 32-bit number representing the bit fields defined by the ATTACHMENT_HINT constants in the
// FIDO Registry of Predefined Values.
AttachmentHint []string
// TcDisplay is a 16-bit number representing a combination of the bit flags defined by the
// TRANSACTION_CONFIRMATION_DISPLAY constants in the FIDO Registry of Predefined Values.
TcDisplay []string
// TcDisplayContentType is the supported MIME content type [RFC2049] for the transaction confirmation display, such
// as text/plain or image/png.
TcDisplayContentType string
// TcDisplayPNGCharacteristics is a list of alternative [DisplayPNGCharacteristicsDescriptor]. Each of these entries
// is one alternative of supported image characteristics for displaying a PNG image.
TcDisplayPNGCharacteristics []DisplayPNGCharacteristicsDescriptor
// AttestationRootCertificates is a list of root certificates. Each element of this array represents a PKIX
// [RFC5280] X.509 certificate that is a valid trust anchor for this authenticator model.
// Multiple certificates might be used for different batches of the same model.
// The array does not represent a certificate chain, but only the trust anchor of that chain.
// A trust anchor can be a root certificate, an intermediate CA certificate, or even the attestation certificate
// itself.
AttestationRootCertificates []*x509.Certificate
// EcdaaTrustAnchors is a list of trust anchors used for ECDAA attestation. This entry MUST be present if and only
// if attestationType includes ATTESTATION_ECDAA.
EcdaaTrustAnchors []EcdaaTrustAnchor
// Icon is a 'data:' url [RFC2397] encoded [PNG] or [SVG11] (light mode) icon for the Authenticator (i.e., depicting
// the security key). This icon is intended to be shown to users by RPs. Use of [SVG11] format is mandatory if any
// of the iconDark, providerLogoLight and/or providerLogoDark is used in addition to icon. Use of [SVG11] is
// recommended if only icon is used. The icon is more specific than the provider logo and should be shown if
// present.
Icon *url.URL
// IconDark is a 'data:' url [RFC2397] encoded [SVG11] dark mode icon for the Authenticator (i.e., depicting the
// security key). This icon is intended to be shown to users by RPs. The icon is more specific than the provider
// logo and should be shown if present.
IconDark *url.URL
// ProviderLogoLight is a 'data:' url [RFC2397] encoded [SVG11] light mode icon for the provider (i.e., logomark of
// the passkey provider). The SVG MUST meet all of the requirements defined in § 4.1 SVG requirements. This icon
// is intended to be shown to users by RPs.
ProviderLogoLight *url.URL
// ProviderLogoDark is a 'data:' url [RFC2397] encoded [SVG11] dark mode icon for the provider (i.e., logomark of
// the passkey provider). The SVG MUST meet all of the requirements defined in § 4.1 SVG requirements. This icon
// is intended to be shown to users by RPs.
ProviderLogoDark *url.URL
// SupportedExtensions is a list of extensions supported by the authenticator.
SupportedExtensions []ExtensionDescriptor
// KeyScope of keys generated and maintained by this authenticator model.
KeyScope KeyScope
// MultiDeviceCredentialSupport describes the support for multi-device credentials.
MultiDeviceCredentialSupport MultiDeviceCredentialSupport
// AuthenticatorGetInfo describes supported versions, extensions, AAGUID of the device and its capabilities.
AuthenticatorGetInfo AuthenticatorGetInfo
// CredentialExportProtocolConfigURL specifies the URL for retrieving the configuration details for the credential
// export protocol (CXP).
CredentialExportProtocolConfigURL *url.URL
}
func (s *Statement) Verifier(x5cis []*x509.Certificate) (opts x509.VerifyOptions) {
roots := x509.NewCertPool()
for _, root := range s.AttestationRootCertificates {
roots.AddCert(root)
}
var intermediates *x509.CertPool
if len(x5cis) > 0 {
intermediates = x509.NewCertPool()
for _, x5c := range x5cis {
intermediates.AddCert(x5c)
}
}
return x509.VerifyOptions{
Roots: roots,
Intermediates: intermediates,
}
}
// StatementJSON is the JSON representation of the [Statement] struct.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-md-keys
type StatementJSON struct {
// LegalHeader contains a legal guide for accessing and using metadata.
LegalHeader string `json:"legalHeader"`
// Aaid is the Authenticator Attestation ID. Set if the authenticator implements FIDO UAF.
Aaid string `json:"aaid"`
// AaGUID is the Authenticator Attestation GUID. Set if the authenticator implements FIDO2.
AaGUID string `json:"aaguid"`
// AttestationCertificateKeyIdentifiers is a list of attestation certificate public key identifiers (hex).
AttestationCertificateKeyIdentifiers []string `json:"attestationCertificateKeyIdentifiers"`
// FriendlyNames contains friendly names of the authenticator in multiple languages.
FriendlyNames map[string]string `json:"friendlyNames"`
// Description is a human-readable, short description of the authenticator, in English.
Description string `json:"description"`
// AlternativeDescriptions is a list of human-readable short descriptions in different languages.
AlternativeDescriptions map[string]string `json:"alternativeDescriptions"`
// AuthenticatorVersion is the earliest trustworthy authenticatorVersion meeting the requirements in this statement.
AuthenticatorVersion uint32 `json:"authenticatorVersion"`
// ProtocolFamily is the FIDO protocol family. The values "uaf", "u2f", and "fido2" are supported.
ProtocolFamily string `json:"protocolFamily"`
// Schema is the Metadata Schema version.
Schema uint16 `json:"schema"`
// Upv is the FIDO unified protocol version(s) supported by this authenticator.
Upv []Version `json:"upv"`
// AuthenticationAlgorithms is the list of authentication algorithms supported by the authenticator.
AuthenticationAlgorithms []AuthenticationAlgorithm `json:"authenticationAlgorithms"`
// PublicKeyAlgAndEncodings is the list of public key formats supported during registration operations.
PublicKeyAlgAndEncodings []PublicKeyAlgAndEncoding `json:"publicKeyAlgAndEncodings"`
// AttestationTypes is the supported attestation type(s).
AttestationTypes []AuthenticatorAttestationType `json:"attestationTypes"`
// UserVerificationDetails is a list of alternative VerificationMethodANDCombinations.
UserVerificationDetails [][]VerificationMethodDescriptor `json:"userVerificationDetails"`
// KeyProtection is the key protection type(s).
KeyProtection []string `json:"keyProtection"`
// IsKeyRestricted indicates if the Uauth private key is restricted to only sign valid FIDO signature assertions.
IsKeyRestricted bool `json:"isKeyRestricted"`
// IsFreshUserVerificationRequired indicates if Uauth key usage always requires a fresh user verification.
IsFreshUserVerificationRequired bool `json:"isFreshUserVerificationRequired"`
// MatcherProtection is the matcher protection type(s).
MatcherProtection []string `json:"matcherProtection"`
// CryptoStrength is the authenticator's overall claimed cryptographic strength in bits.
CryptoStrength uint16 `json:"cryptoStrength"`
// AttachmentHint is the attachment hint(s).
AttachmentHint []string `json:"attachmentHint"`
// TcDisplay is the transaction confirmation display type(s).
TcDisplay []string `json:"tcDisplay"`
// TcDisplayContentType is the supported MIME content type for the transaction confirmation display.
TcDisplayContentType string `json:"tcDisplayContentType"`
// TcDisplayPNGCharacteristics is a list of alternative DisplayPNGCharacteristicsDescriptor.
TcDisplayPNGCharacteristics []DisplayPNGCharacteristicsDescriptor `json:"tcDisplayPNGCharacteristics"`
// AttestationRootCertificates is a list of base64-encoded trust anchor certificates for this authenticator model.
AttestationRootCertificates []string `json:"attestationRootCertificates"`
// EcdaaTrustAnchors is a list of trust anchors used for ECDAA attestation.
EcdaaTrustAnchors []EcdaaTrustAnchor `json:"ecdaaTrustAnchors"`
// Icon is a data: URL encoded PNG or SVG (light mode) icon for the Authenticator.
Icon string `json:"icon"`
// IconDark is a data: URL encoded SVG dark mode icon for the Authenticator.
IconDark string `json:"iconDark"`
// ProviderLogoLight is a data: URL encoded SVG light mode icon for the provider.
ProviderLogoLight string `json:"providerLogoLight"`
// ProviderLogoDark is a data: URL encoded SVG dark mode icon for the provider.
ProviderLogoDark string `json:"providerLogoDark"`
// SupportedExtensions is a list of extensions supported by the authenticator.
SupportedExtensions []ExtensionDescriptor `json:"supportedExtensions"`
// KeyScope of keys generated and maintained by this authenticator model.
KeyScope KeyScope `json:"keyScope"`
// MultiDeviceCredentialSupport describes the support for multi-device credentials.
MultiDeviceCredentialSupport MultiDeviceCredentialSupport `json:"multiDeviceCredentialSupport"`
// AuthenticatorGetInfo describes supported versions, extensions, AAGUID of the device and its capabilities.
AuthenticatorGetInfo AuthenticatorGetInfoJSON `json:"authenticatorGetInfo"`
// CredentialExportProtocolConfigURL specifies the URL for the credential export protocol (CXP) configuration.
CredentialExportProtocolConfigURL string `json:"cxpConfigURL"`
}
// Parse converts StatementJSON into a [Statement] object, validating and parsing its fields. Returns an error on failure.
//
//nolint:gocyclo
func (j StatementJSON) Parse() (statement Statement, err error) {
var aaguid uuid.UUID
if len(j.AaGUID) != 0 {
if aaguid, err = uuid.Parse(j.AaGUID); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing AAGUID value: %w", j.Description, err)
}
}
n := len(j.AttestationRootCertificates)
certificates := make([]*x509.Certificate, n)
for i := 0; i < n; i++ {
if certificates[i], err = mdsParseX509Certificate(j.AttestationRootCertificates[i]); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing attestation root certificate %d value: %w", j.Description, i, err)
}
}
var (
icon, iconDark *url.URL
logoLight, logoDark *url.URL
cxpConfigURL *url.URL
)
if len(j.Icon) != 0 {
if icon, err = url.ParseRequestURI(j.Icon); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing icon value: %w", j.Description, err)
}
}
if len(j.IconDark) != 0 {
if iconDark, err = url.ParseRequestURI(j.IconDark); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing icon dark value: %w", j.Description, err)
}
}
if len(j.ProviderLogoLight) != 0 {
if logoLight, err = url.ParseRequestURI(j.ProviderLogoLight); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing provider logo light value: %w", j.Description, err)
}
}
if len(j.ProviderLogoDark) != 0 {
if logoDark, err = url.ParseRequestURI(j.ProviderLogoDark); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing provider logo dark value: %w", j.Description, err)
}
}
if len(j.CredentialExportProtocolConfigURL) != 0 {
if cxpConfigURL, err = url.ParseRequestURI(j.CredentialExportProtocolConfigURL); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing cxp config url value: %w", j.Description, err)
}
}
var info AuthenticatorGetInfo
if info, err = j.AuthenticatorGetInfo.Parse(); err != nil {
return statement, fmt.Errorf("error occurred parsing statement with description '%s': error occurred parsing authenticator get info value: %w", j.Description, err)
}
return Statement{
LegalHeader: j.LegalHeader,
Aaid: j.Aaid,
AaGUID: aaguid,
AttestationCertificateKeyIdentifiers: j.AttestationCertificateKeyIdentifiers,
FriendlyNames: j.FriendlyNames,
Description: j.Description,
AlternativeDescriptions: j.AlternativeDescriptions,
AuthenticatorVersion: j.AuthenticatorVersion,
ProtocolFamily: j.ProtocolFamily,
Schema: j.Schema,
Upv: j.Upv,
AuthenticationAlgorithms: j.AuthenticationAlgorithms,
PublicKeyAlgAndEncodings: j.PublicKeyAlgAndEncodings,
AttestationTypes: j.AttestationTypes,
UserVerificationDetails: j.UserVerificationDetails,
KeyProtection: j.KeyProtection,
IsKeyRestricted: j.IsKeyRestricted,
IsFreshUserVerificationRequired: j.IsFreshUserVerificationRequired,
MatcherProtection: j.MatcherProtection,
CryptoStrength: j.CryptoStrength,
AttachmentHint: j.AttachmentHint,
TcDisplay: j.TcDisplay,
TcDisplayContentType: j.TcDisplayContentType,
TcDisplayPNGCharacteristics: j.TcDisplayPNGCharacteristics,
AttestationRootCertificates: certificates,
EcdaaTrustAnchors: j.EcdaaTrustAnchors,
Icon: icon,
IconDark: iconDark,
ProviderLogoLight: logoLight,
ProviderLogoDark: logoDark,
SupportedExtensions: j.SupportedExtensions,
KeyScope: j.KeyScope,
MultiDeviceCredentialSupport: j.MultiDeviceCredentialSupport,
AuthenticatorGetInfo: info,
CredentialExportProtocolConfigURL: cxpConfigURL,
}, nil
}
// BiometricStatusReport is a structure representing the BiometricStatusReport dictionary. Contains the current
// BiometricStatusReport of one of the authenticator's biometric component.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-bio-stat-rep
type BiometricStatusReport struct {
// CertLevel is the achieved level of the biometric certification of this biometric component of the authenticator.
CertLevel uint16
// Modality is a single USER_VERIFY short form case-sensitive string name constant, representing biometric modality.
Modality string
// EffectiveDate is an ISO-8601 formatted date since when the certLevel achieved, if applicable. If no date is
// given, the status is assumed to be effective while present.
EffectiveDate time.Time
// CertificationDescriptor describes the externally visible aspects of the Biometric Certification evaluation.
CertificationDescriptor string
// CertificateNumber is the unique identifier for the issued Biometric Certification.
CertificateNumber string
// CertificationPolicyVersion is the version of the Biometric Certification Policy the implementation is Certified
// to, i.e. "1.0.0".
CertificationPolicyVersion string
// CertificationRequirementsVersion is the version of the Biometric Requirements [FIDOBiometricsRequirements] the
// implementation is certified to, i.e. "1.0.0".
CertificationRequirementsVersion string
}
// BiometricStatusReportJSON is the JSON representation of the [BiometricStatusReport] struct.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-bio-stat-rep
type BiometricStatusReportJSON struct {
// CertLevel is the achieved level of the biometric certification of this biometric component.
CertLevel uint16 `json:"certLevel"`
// Modality is a single USER_VERIFY short form string constant representing the biometric modality.
Modality string `json:"modality"`
// EffectiveDate is an ISO-8601 formatted date since when the certLevel was achieved.
EffectiveDate string `json:"effectiveDate"`
// CertificationDescriptor describes the externally visible aspects of the Biometric Certification evaluation.
CertificationDescriptor string `json:"certificationDescriptor"`
// CertificateNumber is the unique identifier for the issued Biometric Certification.
CertificateNumber string `json:"certificateNumber"`
// CertificationPolicyVersion is the version of the Biometric Certification Policy, i.e. "1.0.0".
CertificationPolicyVersion string `json:"certificationPolicyVersion"`
// CertificationRequirementsVersion is the version of the Biometric Requirements, i.e. "1.0.0".
CertificationRequirementsVersion string `json:"certificationRequirementsVersion"`
}
func (j BiometricStatusReportJSON) Parse() (report BiometricStatusReport, err error) {
var effective time.Time
if effective, err = time.Parse(time.DateOnly, j.EffectiveDate); err != nil {
return report, fmt.Errorf("error occurred parsing effective date value: %w", err)
}
return BiometricStatusReport{
CertLevel: j.CertLevel,
Modality: j.Modality,
EffectiveDate: effective,
CertificationDescriptor: j.CertificationDescriptor,
CertificateNumber: j.CertificateNumber,
CertificationPolicyVersion: j.CertificationPolicyVersion,
CertificationRequirementsVersion: j.CertificationRequirementsVersion,
}, nil
}
// StatusReport is a structure representing the StatusReport dictionary. Contains an [AuthenticatorStatus] and additional
// data associated with it, if any.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-stat-rep
type StatusReport struct {
// Status of the authenticator. Additional fields MAY be set depending on this value.
Status AuthenticatorStatus
// EffectiveDate is an ISO-8601 formatted date since when the status code was set, if applicable. If no date is
// given, the status is assumed to be effective while present.
EffectiveDate time.Time
// AuthenticatorVersion is the authenticator version (firmware version) that this status report relates to. In the
// case of FIDO_CERTIFIED* status values, the status applies to higher authenticatorVersions until there is a new
// statusReport.
AuthenticatorVersion uint32
// BatchCertificate is a Base64-encoded [RFC4648] (not base64url!) DER [ITU-X690-2008] PKIX certificate value
// related to the current status, if applicable.
BatchCertificate *x509.Certificate
// Certificate is a Base64-encoded [RFC4648] (not base64url!) DER [ITU-X690-2008] PKIX certificate value related to
// the current status, if applicable. This field will typically not be present if field batchCertificate is present.
Certificate *x509.Certificate
// URL is a HTTPS URL where additional information may be found related to the current status, if applicable.
URL *url.URL
// CertificationDescriptor describes the externally visible aspects of the Authenticator Certification evaluation.
CertificationDescriptor string
// CertificateNumber is the unique identifier for the issued Certification.
CertificateNumber string
// CertificationPolicyVersion is the version of the Authenticator Certification Policy the implementation is
// Certified to, i.e. "1.0.0".
CertificationPolicyVersion string
// CertificationProfiles is a list of certification profile strings. Each entry represents a supported
// certification profile, i.e. "consumer" or "enterprise".
CertificationProfiles []string
// CertificationRequirementsVersion is the Document Version of the Authenticator Security Requirements (DV)
// [FIDOAuthenticatorSecurityRequirements] the implementation is certified to, i.e. "1.2.0".
CertificationRequirementsVersion string
// SunsetDate is an ISO-8601 formatted date since when the status will expire, if applicable. If no date is given,
// the status is assumed to not have a scheduled expiry.
SunsetDate *time.Time
// FIPSRevision is the revision number of the FIPS 140 specification, i.e. "3" in the case of FIPS 140-3. This
// entry MUST be present if and only if the status entry is one of FIPS140_CERTIFIED_L*.
FIPSRevision uint32
// FIPSPhysicalSecurityLevel is the "physical security level" of the FIPS certification. This entry MUST be present
// if and only if the status entry is one of FIPS140_CERTIFIED_L*. It MUST reflect the physical security level
// which might deviate from the overall level.
FIPSPhysicalSecurityLevel uint32
}
// StatusReportJSON is the JSON representation of the [StatusReport] struct.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-stat-rep
type StatusReportJSON struct {
// Status of the authenticator. Additional fields MAY be set depending on this value.
Status AuthenticatorStatus `json:"status"`
// EffectiveDate is an ISO-8601 formatted date since when the status code was set.
EffectiveDate string `json:"effectiveDate"`
// AuthenticatorVersion is the authenticator version (firmware version) that this status report relates to.
AuthenticatorVersion uint32 `json:"authenticatorVersion"`
// BatchCertificate is a Base64-encoded DER PKIX certificate related to the current status.
BatchCertificate string `json:"batchCertificate"`
// Certificate is a Base64-encoded DER PKIX certificate related to the current status.
Certificate string `json:"certificate"`
// URL is a HTTPS URL where additional information may be found related to the current status.
URL string `json:"url"`
// CertificationDescriptor describes the externally visible aspects of the Authenticator Certification evaluation.
CertificationDescriptor string `json:"certificationDescriptor"`
// CertificateNumber is the unique identifier for the issued Certification.
CertificateNumber string `json:"certificateNumber"`
// CertificationPolicyVersion is the version of the Authenticator Certification Policy, i.e. "1.0.0".
CertificationPolicyVersion string `json:"certificationPolicyVersion"`
// CertificationProfiles is a list of supported certification profiles, i.e. "consumer" or "enterprise".
CertificationProfiles []string `json:"certificationProfiles"`
// CertificationRequirementsVersion is the Document Version of the Authenticator Security Requirements, i.e. "1.2.0".
CertificationRequirementsVersion string `json:"certificationRequirementsVersion"`
// SunsetDate is an ISO-8601 formatted date when the status will expire.
SunsetDate string `json:"sunsetDate"`
// FIPSRevision is the revision number of the FIPS 140 specification, i.e. "3" for FIPS 140-3.
FIPSRevision uint32 `json:"fipsRevision"`
// FIPSPhysicalSecurityLevel is the physical security level of the FIPS certification.
FIPSPhysicalSecurityLevel uint32 `json:"fipsPhysicalSecurityLevel"`
}
func (j StatusReportJSON) Parse() (report StatusReport, err error) {
var (
certificate, batchCertificate *x509.Certificate
)
if len(j.Certificate) != 0 {
if certificate, err = mdsParseX509Certificate(j.Certificate); err != nil {
return report, fmt.Errorf("error occurred parsing certificate value: %w", err)
}
}
if len(j.BatchCertificate) != 0 {
if batchCertificate, err = mdsParseX509Certificate(j.BatchCertificate); err != nil {
return report, fmt.Errorf("error occurred parsing batch certificate value: %w", err)
}
}
var (
effective time.Time
sunset *time.Time
)
if effective, err = time.Parse(time.DateOnly, j.EffectiveDate); err != nil {
return report, fmt.Errorf("error occurred parsing effective date value: %w", err)
}
if sunset, err = mdsParseTimePointer(time.DateOnly, j.SunsetDate); err != nil {
return report, fmt.Errorf("error occurred parsing sunset date value: %w", err)
}
var uri *url.URL
if len(j.URL) != 0 {
if uri, err = url.ParseRequestURI(j.URL); err != nil {
if !strings.HasPrefix(j.URL, "http") {
var e error
if uri, e = url.ParseRequestURI(fmt.Sprintf("https://%s", j.URL)); e != nil {
return report, fmt.Errorf("error occurred parsing URL value: %w", err)
}
}
}
}
return StatusReport{
Status: j.Status,
EffectiveDate: effective,
AuthenticatorVersion: j.AuthenticatorVersion,
BatchCertificate: batchCertificate,
Certificate: certificate,
URL: uri,
CertificationDescriptor: j.CertificationDescriptor,
CertificateNumber: j.CertificateNumber,
CertificationPolicyVersion: j.CertificationPolicyVersion,
CertificationProfiles: j.CertificationProfiles,
CertificationRequirementsVersion: j.CertificationRequirementsVersion,
SunsetDate: sunset,
FIPSRevision: j.FIPSRevision,
FIPSPhysicalSecurityLevel: j.FIPSPhysicalSecurityLevel,
}, nil
}
// RogueListEntry is a structure representing the RogueListEntry dictionary.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-service-v3.1.1-rd-20251016.html#sctn-rogue-list-entry
type RogueListEntry struct {
// Sk is the base64url encoding of the rogue authenticator's secret key.
Sk string `json:"sk"`
// Data is the ISO-8601 formatted date since when this entry is effective.
Date string `json:"date"`
}
// CodeAccuracyDescriptor is a structure representing the CodeAccuracyDescriptor dictionary.
// It describes the relevant accuracy/complexity aspects of passcode user verification methods.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-cad
type CodeAccuracyDescriptor struct {
// Base is the numeric system base (radix) of the code, i.e. 10 in the case of decimal digits.
Base uint16 `json:"base"`
// MinLength is the minimum number of digits of the given base required for that code, i.e. 4 in the case of 4
// digits.
MinLength uint16 `json:"minLength"`
// MaxRetries is the maximum number of false attempts before the authenticator will block this method (at least for
// some time). 0 means it will never block.
MaxRetries uint16 `json:"maxRetries"`
// BlockSlowdown is the enforced minimum number of seconds wait time after blocking (i.e. due to forced reboot or
// similar). 0 means this user verification method will be blocked, either permanently, or until an alternative user
// verification method method succeeded. All alternative user verification methods MUST be specified appropriately
// in the Metadata in userVerificationDetails.
BlockSlowdown uint16 `json:"blockSlowdown"`
}
// BiometricAccuracyDescriptor is a structure representing the BiometricAccuracyDescriptor dictionary.
// It describes relevant accuracy/complexity aspects in the case of a biometric user verification method.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-bad
type BiometricAccuracyDescriptor struct {
// SelfAttestedFRR is the false rejection rate [ISO19795-1] for a single template, i.e. the percentage of
// verification transactions with truthful claims of identity that are incorrectly denied.
SelfAttestedFRR float64 `json:"selfAttestedFRR"`
// SelfAttestedFAR is the false acceptance rate [ISO19795-1] for a single template, i.e. the percentage of
// verification transactions with wrongful claims of identity that are incorrectly confirmed.
SelfAttestedFAR float64 `json:"selfAttestedFAR"`
// ImposterAttackPresentationAcceptRateThreshold is the threshold for Impostor Attack Presentation Accept Rate
// (IAPAR) is the proportion of impostor attack presentations using the same presentation attack instrument (PAI)
// species that result in accept [isoiec-30107-3]. For biometric certification requirements
// [FIDOBiometricsRequirements], certification can be achieved for an IAPAR threshold of less than 7% OR less than
// 15% for each of the PAI species tested.
ImposterAttackPresentationAcceptRateThreshold float64 `json:"iAPARThreshold"`
// MaxTemplates is the maximum number of alternative templates from different fingers allowed.
MaxTemplates uint16 `json:"maxTemplates"`
// MaxRetries is the maximum number of false attempts before the authenticator will block this method (at least for
// some time). 0 means it will never block.
MaxRetries uint16 `json:"maxRetries"`
// BlockSlowdown is the enforced minimum number of seconds wait time after blocking (i.e. due to forced reboot or
// similar).0 means that this user verification method will be blocked either permanently or until an alternative
// user verification method succeeded. All alternative user verification methods MUST be specified appropriately in
// the metadata in userVerificationDetails.
BlockSlowdown uint16 `json:"blockSlowdown"`
}
// PatternAccuracyDescriptor is a structure representing the PatternAccuracyDescriptor dictionary.
// It describes relevant accuracy/complexity aspects in the case that a pattern is used as the user verification method.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-pad
type PatternAccuracyDescriptor struct {
// MinComplexity is the number of possible patterns (having the minimum length) out of which exactly one would be
// the right one, i.e. 1/probability in the case of equal distribution.
MinComplexity uint32 `json:"minComplexity"`
// MaxRetries is the maximum number of false attempts before the authenticator will block authentication using this
// method (at least temporarily). 0 means it will never block.
MaxRetries uint16 `json:"maxRetries"`
// BlockSlowdown is the enforced minimum number of seconds wait time after blocking (due to forced reboot or similar
// mechanism). 0 means this user verification method will be blocked, either permanently, or until an alternative
// user verification method method succeeded. All alternative user verification methods MUST be specified
// appropriately in the metadata under userVerificationDetails.
BlockSlowdown uint16 `json:"blockSlowdown"`
}
// VerificationMethodDescriptor is a structure representing the VerificationMethodDescriptor dictionary.
// It describes a descriptor for a specific base user verification method as implemented by the authenticator.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-vmd
type VerificationMethodDescriptor struct {
// UserVerificationMethod is a single USER_VERIFY constant (see [FIDORegistry]), not a bit flag combination. This
// value MUST be non-zero.
UserVerificationMethod string `json:"userVerificationMethod"`
// CaDesc nay optionally be used in the case of method USER_VERIFY_PASSCODE.
CaDesc CodeAccuracyDescriptor `json:"caDesc"`
// BaDesc may optionally be used in the case of method USER_VERIFY_FINGERPRINT, USER_VERIFY_VOICEPRINT,
// USER_VERIFY_FACEPRINT, USER_VERIFY_EYEPRINT, or USER_VERIFY_HANDPRINT.
BaDesc BiometricAccuracyDescriptor `json:"baDesc"`
// PaDesc may optionally be used in case of method USER_VERIFY_PATTERN.
PaDesc PatternAccuracyDescriptor `json:"paDesc"`
}
// RGBPaletteEntry is a structure representing the RGBPaletteEntry dictionary.
// It describes an RGB three-sample tuple palette entry.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-rgbpe
type RGBPaletteEntry struct {
// R is the red channel sample value.
R uint16 `json:"r"`
// G is the green channel sample value.
G uint16 `json:"g"`
// B is the blue channel sample value.
B uint16 `json:"b"`
}
// DisplayPNGCharacteristicsDescriptor is a structure representing the DisplayPNGCharacteristicsDescriptor MDS3.1
// dictionary. It describes a PNG image characteristics as defined in the PNG [PNG] spec for IHDR (image header) and
// PLTE (palette table).
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-dpngcd
type DisplayPNGCharacteristicsDescriptor struct {
// Width of the image.
Width uint32 `json:"width"`
// Height of the image.
Height uint32 `json:"height"`
// BitDepth is bits per sample or per palette index.
BitDepth byte `json:"bitDepth"`
// ColorType defines the PNG image type.
ColorType byte `json:"colorType"`
// Compression method used to compress the image data.
Compression byte `json:"compression"`
// Filter method is the preprocessing method applied to the image data before compression.
Filter byte `json:"filter"`
// Interlace method is the transmission order of the image data.
Interlace byte `json:"interlace"`
// Plte is a number 1 to 256 representing palette entries.
Plte []RGBPaletteEntry `json:"plte"`
}
// EcdaaTrustAnchor is a structure representing the EcdaaTrustAnchor dictionary.
// In the case of ECDAA attestation, the ECDAA-Issuer's trust anchor MUST be specified in this field.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-ecdaata
type EcdaaTrustAnchor struct {
// X is the base64url encoding of the result of ECPoint2ToB of the ECPoint2 X.
X string `json:"X"`
// Y is the base64url encoding of the result of ECPoint2ToB of the ECPoint2 Y.
Y string `json:"Y"`
// C is the base64url encoding of the result of BigNumberToB(c).
C string `json:"c"`
// SX is the base64url encoding of the result of BigNumberToB(sx).
SX string `json:"sx"`
// SY is the base64url encoding of the result of BigNumberToB(sy).
SY string `json:"sy"`
// G1Curve is the name of the Barreto-Naehrig elliptic curve for G1. "BN_P256", "BN_P638", "BN_ISOP256", and
// "BN_ISOP512" are supported.
G1Curve string `json:"G1Curve"`
}
// ExtensionDescriptor is a structure representing the ExtensionDescriptor dictionary.
// This descriptor contains an extension supported by the authenticator.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-ed
type ExtensionDescriptor struct {
// ID identifies the extension.
ID string `json:"id"`
// Tag of the extension if this was assigned. TAGs are assigned to extensions if they could appear in an assertion.
Tag uint16 `json:"tag"`
// Data contains arbitrary data further describing the extension and/or data needed to correctly process the
// extension.
Data string `json:"data"`
// FailIfUnknown indicates whether unknown extensions must be ignored (false) or must lead to an error (true) when
// the extension is to be processed by the FIDO Server, FIDO Client, ASM, or FIDO Authenticator.
FailIfUnknown bool `json:"fail_if_unknown"`
}
// Version is a structure representing the Version FIDO UAF Protocol 1.2 dictionary and represents a generic version
// with major and minor fields.
//
// See: https://fidoalliance.org/specs/fido-uaf-v1.2-ps-20201020/fido-uaf-protocol-v1.2-ps-20201020.html#version-interface
type Version struct {
// Major version.
Major uint16 `json:"major"`
// Minor version.
Minor uint16 `json:"minor"`
}
// AuthenticatorGetInfo is a structure representing the AuthenticatorGetInfo dictionary.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-agid
type AuthenticatorGetInfo struct {
// Versions is a list of supported versions.
Versions []string
// Extensions is a list of supported extensions.
Extensions []string
// AaGUID is the claimed AAGUID.
AaGUID uuid.UUID
// Options is a list of supported options.
Options map[string]bool
// MaxMsgSize is the maximum message size supported by the authenticator.
MaxMsgSize uint
// PivUvAuthProtocols is a list of supported PIN/UV auth protocols in order of decreasing authenticator preference.
PivUvAuthProtocols []uint
// MaxCredentialCountInList is the maximum number of credentials supported in credentialID list at a time by the
// authenticator.
MaxCredentialCountInList uint
// MaxCredentialIdLength is the maximum Credential ID Length supported by the authenticator.
MaxCredentialIdLength uint
// Transports is the list of supported transports.
Transports []string
// Algorithms is the list of supported algorithms for credential generation, as specified in WebAuthn.
Algorithms []PublicKeyCredentialParameters
// MaxSerializedLargeBlobArray is the maximum size, in bytes, of the serialized large-blob array that this
// authenticator can store.
MaxSerializedLargeBlobArray uint
// ForcePINChange indicates if the PIN must be changed.
ForcePINChange bool
// MinPINLength specifies the current minimum PIN length, in Unicode code points, the authenticator enforces for ClientPIN.
MinPINLength uint
// FirmwareVersion indicates the firmware version of the authenticator model identified by AAGUID.
FirmwareVersion uint
// MaxCredBlobLength indicates the maximum credential blob length in bytes supported by the authenticator.
MaxCredBlobLength uint
// MaxRPIDsForSetMinPINLength specifies the max number of RP IDs that authenticator can set via setMinPINLength
// subcommand.
MaxRPIDsForSetMinPINLength uint
// PreferredPlatformUvAttempts specifies the preferred number of invocations of the
// getPinUvAuthTokenUsingUvWithPermissions subCommand the platform may attempt before falling back to the
// getPinUvAuthTokenUsingPinWithPermissions subCommand or displaying an error.
PreferredPlatformUvAttempts uint
// UvModality specifies the user verification modality supported by the authenticator via authenticatorClientPIN's
// getPinUvAuthTokenUsingUvWithPermissions subcommand.
UvModality uint
// Certifications specifies a list of authenticator certifications.
Certifications map[string]float64
// RemainingDiscoverableCredentials if present indicates the estimated number of additional discoverable credentials
// that can be stored.
RemainingDiscoverableCredentials uint
// VendorPrototypeConfigCommands if present the authenticator supports the authenticatorConfig vendorPrototype
// subcommand, and its value is a list of authenticatorConfig vendorCommandId values supported, which MAY be empty.
VendorPrototypeConfigCommands []uint
}
// AuthenticatorGetInfoJSON is the JSON representation of the [AuthenticatorGetInfo] struct. The members mirror the
// fields returned by the CTAP authenticatorGetInfo command.
//
// See: https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.1-ps-20250521.html#sctn-type-agid
type AuthenticatorGetInfoJSON struct {
// Versions is a list of supported CTAP versions.
Versions []string `json:"versions"`
// Extensions is a list of supported extensions.
Extensions []string `json:"extensions"`
// AaGUID is the claimed AAGUID.
AaGUID string `json:"aaguid"`
// Options is a map of supported options.
Options map[string]bool `json:"options"`
// MaxMsgSize is the maximum message size supported by the authenticator.
MaxMsgSize uint `json:"maxMsgSize"`
// PivUvAuthProtocols is a list of supported PIN/UV auth protocols in order of decreasing authenticator preference.
PivUvAuthProtocols []uint `json:"pinUvAuthProtocols"`
// MaxCredentialCountInList is the maximum number of credentials supported in credentialID list at a time.
MaxCredentialCountInList uint `json:"maxCredentialCountInList"`
// MaxCredentialIdLength is the maximum Credential ID Length supported by the authenticator.
MaxCredentialIdLength uint `json:"maxCredentialIdLength"`
// Transports is the list of supported transports.
Transports []string `json:"transports"`
// Algorithms is the list of supported algorithms for credential generation.
Algorithms []PublicKeyCredentialParameters `json:"algorithms"`
// MaxSerializedLargeBlobArray is the maximum size, in bytes, of the serialized large-blob array.
MaxSerializedLargeBlobArray uint `json:"maxSerializedLargeBlobArray"`
// ForcePINChange indicates if the PIN must be changed.
ForcePINChange bool `json:"forcePINChange"`
// MinPINLength specifies the current minimum PIN length, in Unicode code points.
MinPINLength uint `json:"minPINLength"`
// FirmwareVersion indicates the firmware version of the authenticator model identified by AAGUID.
FirmwareVersion uint `json:"firmwareVersion"`
// MaxCredBlobLength indicates the maximum credential blob length in bytes.
MaxCredBlobLength uint `json:"maxCredBlobLength"`
// MaxRPIDsForSetMinPINLength specifies the max number of RP IDs that can be set via setMinPINLength subcommand.
MaxRPIDsForSetMinPINLength uint `json:"maxRPIDsForSetMinPINLength"`
// PreferredPlatformUvAttempts specifies the preferred number of UV attempts before falling back to PIN.
PreferredPlatformUvAttempts uint `json:"preferredPlatformUvAttempts"`
// UvModality specifies the user verification modality supported by the authenticator.
UvModality uint `json:"uvModality"`
// Certifications specifies a map of authenticator certifications.
Certifications map[string]float64 `json:"certifications"`
// RemainingDiscoverableCredentials indicates the estimated number of additional discoverable credentials that
// can be stored.
RemainingDiscoverableCredentials uint `json:"remainingDiscoverableCredentials"`
// VendorPrototypeConfigCommands is a list of supported authenticatorConfig vendorCommandId values.
VendorPrototypeConfigCommands []uint `json:"vendorPrototypeConfigCommands"`
}
func (j AuthenticatorGetInfoJSON) Parse() (info AuthenticatorGetInfo, err error) {
var aaguid uuid.UUID
if len(j.AaGUID) != 0 {
if aaguid, err = uuid.Parse(j.AaGUID); err != nil {
return info, fmt.Errorf("error occurred parsing AAGUID value: %w", err)
}
}
return AuthenticatorGetInfo{
Versions: j.Versions,
Extensions: j.Extensions,
AaGUID: aaguid,
Options: j.Options,
MaxMsgSize: j.MaxMsgSize,
PivUvAuthProtocols: j.PivUvAuthProtocols,
MaxCredentialCountInList: j.MaxCredentialCountInList,
MaxCredentialIdLength: j.MaxCredentialIdLength,
Transports: j.Transports,
Algorithms: j.Algorithms,
MaxSerializedLargeBlobArray: j.MaxSerializedLargeBlobArray,
ForcePINChange: j.ForcePINChange,
MinPINLength: j.MinPINLength,
FirmwareVersion: j.FirmwareVersion,
MaxCredBlobLength: j.MaxCredBlobLength,
MaxRPIDsForSetMinPINLength: j.MaxRPIDsForSetMinPINLength,
PreferredPlatformUvAttempts: j.PreferredPlatformUvAttempts,
UvModality: j.UvModality,
Certifications: j.Certifications,
RemainingDiscoverableCredentials: j.RemainingDiscoverableCredentials,
VendorPrototypeConfigCommands: j.VendorPrototypeConfigCommands,
}, nil
}
// MDSGetEndpointsRequest is the request sent to the conformance metadata getEndpoints endpoint.
type MDSGetEndpointsRequest struct {
// Endpoint is the URL of the local server endpoint, i.e. https://webauthn.io/
Endpoint string `json:"endpoint"`
}
// MDSGetEndpointsResponse is the response received from a conformance metadata getEndpoints request.
type MDSGetEndpointsResponse struct {
// Status is the status of the response.
Status string `json:"status"`
// Result is an array of urls, each pointing to a MetadataTOCPayload.
Result []string `json:"result"`
}
// DefaultUndesiredAuthenticatorStatuses returns a copy of the defaultUndesiredAuthenticatorStatus slice.
func DefaultUndesiredAuthenticatorStatuses() []AuthenticatorStatus {
undesired := make([]AuthenticatorStatus, len(defaultUndesiredAuthenticatorStatus))
copy(undesired, defaultUndesiredAuthenticatorStatus[:])
return undesired
}
// EntryError represents an [EntryJSON] that failed to parse, along with the error that occurred.
type EntryError struct {
// Error is the parsing error that occurred.
Error error
// EntryJSON is the raw JSON entry that failed to parse.
EntryJSON
}