{"record":{"id":"417097a44637b854","repo":"gravitational/teleport","slug":"u2f-devices-cannot-do-passwordless","errorCode":null,"errorMessage":"U2F devices cannot do passwordless","messagePattern":"U2F devices cannot do passwordless","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"lib/auth/webauthncli/fido2.go","lineNumber":71,"sourceCode":"\tfido2DeviceTimeout = 30 * time.Second\n\n\t// Operation retry interval.\n\t// Keep it less frequent than 5Hz / 0.2s.\n\tfido2RetryInterval = 500 * time.Millisecond\n\n\t// Timeout for touch.Status operations.\n\t// Keep it less frequent than 5Hz / 0.2s.\n\tfido2TouchMaxWait = 200 * time.Millisecond\n)\n\n// User-friendly device filter errors.\nvar (\n\terrHasExcludedCredential = errors.New(\"device already holds a registered credential\")\n\terrNoPasswordless        = errors.New(\"device not registered for passwordless\")\n\terrNoPlatform            = errors.New(\"device cannot fulfill platform attachment requirement\")\n\terrNoRK                  = errors.New(\"device lacks resident key capabilities\")\n\terrNoUV                  = errors.New(\"device lacks PIN or user verification capabilities necessary to support passwordless\")\n\terrPasswordlessU2F       = errors.New(\"U2F devices cannot do passwordless\")\n)\n\n// TouchRequest abstracts *libfido2.TouchRequest for testing.\ntype TouchRequest interface {\n\tStatus(timeout time.Duration) (touched bool, err error)\n\tStop() error\n}\n\n// FIDODevice abstracts *libfido2.Device for testing.\ntype FIDODevice interface {\n\t// Info mirrors libfido2.Device.Info.\n\tInfo() (*libfido2.DeviceInfo, error)\n\n\t// IsFIDO2 mirrors libfido2.Device.IsFIDO2.\n\tIsFIDO2() (bool, error)\n\n\t// Cancel mirrors libfido2.Device.Cancel.\n\tCancel() error","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/webauthncli/fido2.go#L53-L89","documentation":"errPasswordlessU2F is a user-friendly device filter error: the device is a legacy U2F (CTAP1) authenticator — info.fido2 false — and the ceremony requires features U2F cannot do (resident keys or user verification), so it is filtered out instead of failing mid-ceremony.","triggerScenarios":"fido2.go:198 (passwordless path: !info.fido2 && (uv || passwordless)) and fido2.go:517 (registration path: !info.fido2 && (rrk || uv)) — any U2F-only device (e.g. original YubiKey designed for U2F, YubiKey Neo) in an RK/UV-requiring flow.","commonSituations":"First-generation FIDO U2F security keys used where passwordless/MFA-with-UV is required; very old YubiKeys; company fleet of U2F-only tokens after a policy upgrade to passwordless.","solutions":["Replace the token with a FIDO2-capable security key (CTAP2, e.g. YubiKey 5 series).","Use the plain U2F/WebAuthn MFA flow (tap only, no passwordless/UV requirements).","Relax the ceremony requirements (no rrk/uv) if U2F devices must remain supported."],"exampleFix":"// before: passwordless required, U2F-only fleet\n// after: allow plain MFA or upgrade keys\n$ tsh mfa add --type=webauthn  // with a FIDO2 key","handlingStrategy":"fallback","validationCode":"// detect U2F-only devices before passwordless/UV flows\n// ykman info / device info shows CTAP1 (U2F) only?","typeGuard":null,"tryCatchPattern":"err := login(ctx)\nif err != nil && strings.Contains(err.Error(), \"U2F devices cannot do passwordless\") {\n\treturn legacyMFALogin(ctx) // plain U2F tap flow\n}","preventionTips":["Inventory your fleet's security keys and identify U2F-only tokens.","Migrate to FIDO2 keys before enabling passwordless/UV policies.","Keep a plain-MFA login path available for legacy tokens."],"tags":["fido2","u2f","passwordless","webauthn"],"backgroundTag":"authenticator-u2f-only","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}