package webauthn import ( "errors" "fmt" "github.com/go-webauthn/webauthn/protocol" "github.com/sirupsen/logrus" "github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/model" ) // IsCredentialCreationDiscoverable returns true if the *protocol.ParsedCredentialCreationData indicates a discoverable // credential was generated. func IsCredentialCreationDiscoverable(logger *logrus.Entry, response *protocol.ParsedCredentialCreationData) (discoverable bool) { if value, ok := response.ClientExtensionResults[ExtensionCredProps]; ok { switch credentialProperties := value.(type) { case map[string]any: var v any if v, ok = credentialProperties[ExtensionCredPropsResidentKey]; ok { if discoverable, ok = v.(bool); ok { logger.WithFields(map[string]any{LogFieldDiscoverable: discoverable}).Trace("Determined Credential Discoverability via Client Extension Results") return discoverable } else { logger.WithFields(map[string]any{LogFieldDiscoverable: false}).Trace("Assuming Credential Discoverability is false as the 'rk' field for the 'credProps' extension in the Client Extension Results was not a boolean") } } else { logger.WithFields(map[string]any{LogFieldDiscoverable: false}).Trace("Assuming Credential Discoverability is false as the 'rk' field for the 'credProps' extension was missing from the Client Extension Results") } return false default: logger.WithFields(map[string]any{LogFieldDiscoverable: false}).Trace("Assuming Credential Discoverability is false as the 'credProps' extension in the Client Extension Results does not appear to be a dictionary") return false } } logger.WithFields(map[string]any{LogFieldDiscoverable: false}).Trace("Assuming Credential Discoverability is false as the 'credProps' extension is missing from the Client Extension Results") return false } func ValidateCredentialAllowed(config *schema.WebAuthn, credential *model.WebAuthnCredential) (err error) { if config.Filtering.ProhibitBackupEligibility && credential.BackupEligible { return fmt.Errorf("error checking webauthn credential: filters have been configured which prohibit credentials that are backup eligible") } if len(config.Filtering.PermittedAAGUIDs) != 0 { for _, aaguid := range config.Filtering.PermittedAAGUIDs { if credential.AAGUID.UUID == aaguid { return nil } } return fmt.Errorf("error checking webauthn credential: filters have been configured which explicitly require only permitted AAGUID's be used and '%s' is not permitted", credential.AAGUID.UUID) } for _, aaguid := range config.Filtering.ProhibitedAAGUIDs { if credential.AAGUID.UUID == aaguid { return fmt.Errorf("error checking webauthn credential: filters have been configured which prohibit the AAGUID '%s' from registration", aaguid) } } return nil } func FormatError(err error) error { out := &protocol.Error{} if errors.As(err, &out) { if len(out.DevInfo) == 0 { if len(out.Type) == 0 { return err } return fmt.Errorf("%w (%s)", err, out.Type) } if len(out.Type) == 0 { return fmt.Errorf("%w: %s", err, out.DevInfo) } return fmt.Errorf("%w (%s): %s", err, out.Type, out.DevInfo) } return err }