Skip to content

Commit

Permalink
feat: refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-elliott committed Jun 9, 2024
1 parent a785de5 commit 74e2212
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 159 deletions.
74 changes: 0 additions & 74 deletions metadata/memory.go

This file was deleted.

13 changes: 12 additions & 1 deletion metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (m *Metadata) ToMap() (metadata map[uuid.UUID]*MetadataBLOBPayloadEntry) {
metadata = make(map[uuid.UUID]*MetadataBLOBPayloadEntry)

for _, entry := range m.Parsed.Entries {
if entry.AaGUID.ID() != 0 {
if entry.AaGUID != uuid.Nil {
metadata[entry.AaGUID] = &entry
}
}
Expand Down Expand Up @@ -875,3 +875,14 @@ type MDSGetEndpointsResponse struct {
// 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))

for i := range defaultUndesiredAuthenticatorStatus {
undesired[i] = defaultUndesiredAuthenticatorStatus[i]
}

return undesired
}
11 changes: 9 additions & 2 deletions metadata/passkey_authenticator.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package metadata

// PasskeyAuthenticator is a type that represents the schema from the Passkey Developer AAGUID listing.
//
// See: https://github.com/passkeydeveloper/passkey-authenticator-aaguids
type PasskeyAuthenticator map[string]PassKeyAuthenticatorAAGUID

// PassKeyAuthenticatorAAGUID is a type that represents the indivudal schema entry from the Passkey Developer AAGUID
// listing. Used with PasskeyAuthenticator.
//
// See: https://github.com/passkeydeveloper/passkey-authenticator-aaguids
type PassKeyAuthenticatorAAGUID struct {
Name string `json:"name"`
IconDark string `json:"icon_dark"`
IconLight string `json:"icon_light"`
IconDark string `json:"icon_dark,omitempty"`
IconLight string `json:"icon_light,omitempty"`
}
12 changes: 0 additions & 12 deletions metadata/providers/memory/const.go

This file was deleted.

55 changes: 53 additions & 2 deletions metadata/providers/memory/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,61 @@ import (
"github.com/go-webauthn/webauthn/metadata"
)

type Opt func(*Provider)
// Option describes an optional pattern for this provider.
type Option func(*Provider)

func WithMetadata(metadata map[uuid.UUID]*metadata.MetadataBLOBPayloadEntry) Opt {
// WithMetadata provides the required metadata for the memory provider.
func WithMetadata(metadata map[uuid.UUID]*metadata.MetadataBLOBPayloadEntry) Option {
return func(provider *Provider) {
provider.mds = metadata
}
}

// WithValidateEntry requires that the provided metadata has an entry for the given authenticator to be considered
// valid. By default an AAGUID which has a zero value should fail validation if WithValidateEntryPermitZeroAAGUID is not
// provided with the value of true.
func WithValidateEntry(require bool) Option {
return func(provider *Provider) {
provider.entry = require
}
}

// WithValidateEntryPermitZeroAAGUID is an option that permits a zero'd AAGUID from an attestation statement to
// automatically pass metadata validations. Generally helpful to use with WithValidateEntry.
func WithValidateEntryPermitZeroAAGUID(permit bool) Option {
return func(provider *Provider) {
provider.entryPermitZero = permit
}
}

// WithValidateTrustAnchor when set to true enables the validation of the attestation statement against the trust anchor
// from the metadata.
func WithValidateTrustAnchor(validate bool) Option {
return func(provider *Provider) {
provider.anchors = validate
}
}

// WithValidateStatus when set to true enables the validation of the attestation statments AAGUID against the desired
// and undesired metadata.AuthenticatorStatus lists.
func WithValidateStatus(validate bool) Option {
return func(provider *Provider) {
provider.status = validate
}
}

// WithStatusUndesired provides the list of statuses which are considered undesirable for status report validation
// purposes. Should be used with WithValidateStatus set to true.
func WithStatusUndesired(statuses []metadata.AuthenticatorStatus) Option {
return func(provider *Provider) {
provider.undesired = statuses
}
}

// WithStatusDesired provides the list of statuses which are considered desired and will be required for status report
// validation purposes. Should be used with WithValidateStatus set to true.
func WithStatusDesired(statuses []metadata.AuthenticatorStatus) Option {
return func(provider *Provider) {
provider.desired = statuses
}
}
84 changes: 36 additions & 48 deletions metadata/providers/memory/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,31 @@ import (
"github.com/go-webauthn/webauthn/metadata"
)

// New returns a new memory provider given a map, list of undesired AuthenticatorStatus types, a
// required boolean which if true will cause registrations to fail if no metadata entry is found for the attestation
// statement, and a validate boolean which determines if trust anchors should be validated by this provider during
// registration.
//
// If the undesired status slice is nil it will use a default value. You must explicitly use an empty slice to disable
// this functionality.
func New(mds map[uuid.UUID]*metadata.MetadataBLOBPayloadEntry, undesired []metadata.AuthenticatorStatus, required, validate bool) *Provider {
if undesired == nil {
undesired = make([]metadata.AuthenticatorStatus, len(defaultUndesiredAuthenticatorStatus))

for i := range defaultUndesiredAuthenticatorStatus {
undesired[i] = defaultUndesiredAuthenticatorStatus[i]
}
}
// New returns a new memory provider given a set of functional Option's.
func New(opts ...Option) (provider *Provider) {

return &Provider{
mds: mds,
undesired: undesired,
require: required,
validate: validate,
provider = &Provider{
undesired: metadata.DefaultUndesiredAuthenticatorStatuses(),
}
}

type Provider struct {
mds map[uuid.UUID]*metadata.MetadataBLOBPayloadEntry
desired []metadata.AuthenticatorStatus
undesired []metadata.AuthenticatorStatus
require bool
validate bool
status bool
}

func (p *Provider) GetTrustAnchorValidation(ctx context.Context) (validate bool) {
return p.validate
}
for _, opt := range opts {
opt(provider)
}

func (p *Provider) GetAuthenticatorStatusValidation(ctx context.Context) (validate bool) {
return len(p.undesired) > 0
return provider
}

func (p *Provider) GetRequireEntry(ctx context.Context) (require bool) {
return p.require
// Provider is a concrete implementation of the metadata.Provider that utilizes memory for validation. This provider is
// a simple one-shot that doesn't perform any locking, provide dynamic functionality, or download the metadata at any
// stage (it expects it's provided via one of the Option's).
type Provider struct {
mds map[uuid.UUID]*metadata.MetadataBLOBPayloadEntry
desired []metadata.AuthenticatorStatus
undesired []metadata.AuthenticatorStatus
entry bool
entryPermitZero bool
anchors bool
status bool
}

func (p *Provider) GetEntry(ctx context.Context, aaguid uuid.UUID) (entry *metadata.MetadataBLOBPayloadEntry, err error) {
Expand All @@ -67,20 +49,26 @@ func (p *Provider) GetEntry(ctx context.Context, aaguid uuid.UUID) (entry *metad
return nil, nil
}

func (p *Provider) ValidateAuthenticatorStatusReports(ctx context.Context, reports []metadata.StatusReport) (err error) {
if !p.status {
return nil
}
func (p *Provider) GetValidateEntry(ctx context.Context) (require bool) {
return p.entry
}

return metadata.ValidateStatusReports(reports, p.desired, p.undesired)
func (p *Provider) GetValidateEntryPermitZeroAAGUID(ctx context.Context) (skip bool) {
return p.entryPermitZero
}

func (p *Provider) GetValidateTrustAnchor(ctx context.Context) (validate bool) {
return p.anchors
}

func (p *Provider) GetAuthenticatorStatusIsUndesired(ctx context.Context, status metadata.AuthenticatorStatus) (undesired bool) {
for _, s := range p.undesired {
if s == status {
return true
}
func (p *Provider) GetValidateStatus(ctx context.Context) (validate bool) {
return p.status
}

func (p *Provider) ValidateStatusReports(ctx context.Context, reports []metadata.StatusReport) (err error) {
if !p.status {
return nil
}

return false
return metadata.ValidateStatusReports(reports, p.desired, p.undesired)
}
21 changes: 15 additions & 6 deletions metadata/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,25 @@ type Provider interface {
// GetEntry returns a MDS3 payload entry given a AAGUID. This
GetEntry(ctx context.Context, aaguid uuid.UUID) (entry *MetadataBLOBPayloadEntry, err error)

// GetRequireEntry returns true if this provider requires an entry to exist with a AAGUID matching the attestation
// GetValidateEntry returns true if this provider requires an entry to exist with a AAGUID matching the attestation
// statement during registration.
GetRequireEntry(ctx context.Context) (require bool)
GetValidateEntry(ctx context.Context) (validate bool)

// GetTrustAnchorValidation returns true if trust anchor validation of attestation statements is enforced during
// GetValidateEntryPermitZeroAAGUID returns true if attestation statements with zerod AAGUID should be permitted
// when considering the result from GetValidateEntry. i.e. if the AAGUID is zeroed, and GetValidateEntry returns
// true, and this implementation returns true, the attestation statement will pass validation.
GetValidateEntryPermitZeroAAGUID(ctx context.Context) (skip bool)

// GetValidateTrustAnchor returns true if trust anchor validation of attestation statements is enforced during
// registration.
GetTrustAnchorValidation(ctx context.Context) (validate bool)
GetValidateTrustAnchor(ctx context.Context) (validate bool)

// GetValidateStatus returns true if the status reports for an authenticator should be validated against desired and
// undesired statuses.
GetValidateStatus(ctx context.Context) (validate bool)

// ValidateAuthenticatorStatusReports returns nil if the provided authenticator status reports are desired.
ValidateAuthenticatorStatusReports(ctx context.Context, reports []StatusReport) (err error)
// ValidateStatusReports returns nil if the provided authenticator status reports are desired.
ValidateStatusReports(ctx context.Context, reports []StatusReport) (err error)
}

var (
Expand Down
Loading

0 comments on commit 74e2212

Please sign in to comment.