{"record":{"id":"a3e877d953c5c5a5","repo":"gravitational/teleport","slug":"device-cannot-fulfill-platform-attachment-requirem","errorCode":null,"errorMessage":"device cannot fulfill platform attachment requirement","messagePattern":"device cannot fulfill platform attachment requirement","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"lib/auth/webauthncli/fido2.go","lineNumber":68,"sourceCode":"\n\t// Timeout for blocking operations.\n\t// Functions fail with FIDO_ERR_RX on timeout.\n\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)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/webauthncli/fido2.go#L50-L86","documentation":"errNoPlatform is a user-friendly device filter error returned when a ceremony requires platform attachment (plat=true, e.g. Touch ID/passkeys attached to the device) but the connected FIDO2 device is a roaming authenticator (USB/NFC key), not a platform device.","triggerScenarios":"fido2.go:519 — plat && !info.plat during device filtering in registration/login that requests authenticatorAttachment=platform.","commonSituations":"Server-side config requires platform authenticator (e.g. for attestation or passkey policy) while the user uses a USB YubiKey; mixing platform-only policies with hardware keys.","solutions":["Use the device's built-in platform authenticator (Touch ID/Windows Hello) for this flow.","If a roaming key should be accepted, relax the authenticator attachment requirement (attachment auto/plat=false) in the WebAuthn config.","Check teleport's WebAuthn configuration for attachment requirements and adjust them to your hardware."],"exampleFix":"// before (server credential options)\n\"authenticatorSelection\": {\"authenticatorAttachment\": \"platform\"}\n// after\n\"authenticatorSelection\": {\"authenticatorAttachment\": null} // allow cross-platform keys","handlingStrategy":"validation","validationCode":"// confirm attachment requirements match hardware\n// plat requirement true? use built-in Touch ID / Windows Hello instead of a USB key","typeGuard":null,"tryCatchPattern":"err := login(ctx)\nif err != nil && strings.Contains(err.Error(), \"platform attachment requirement\") {\n\t// retry with platform authenticator or relax attachment config\n}","preventionTips":["Only require platform attachment when targeting laptops/phones with built-in authenticators.","Prefer authenticatorAttachment auto when hardware keys are also in use.","Document which MFA devices satisfy which WebAuthn policies."],"tags":["fido2","platform-authenticator","webauthn","attachment"],"backgroundTag":"authenticator-attachment-mismatch","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}