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 }