如何在 iOS 上启用指纹 WebAuthn

How to enable fingerprint WebAuthn on iOS

阅读 extensive documentation about WebAuth API 后,我无法在 iOS 上成功启用平台身份验证。
我已经尝试将 Authenticator Attachment 设置为跨平台和平台,除了 iOS:

之外它们产生了一致的结果
╭────────────────┬───────────────────────┬────────────────────────────┬────────────────────────────┬───────────────────────────────────────────────╮
│   Attachment   │       Windows 10      │         Android 8          │       MacOS Catalina       │             iOS 13                            │
│                │       Edge/Chrome     │        Chrome/Opera        │        Chrome/Safari       │      Webkit(Everything else is this anyways)  │
╞════════════════╬═══════════════════════╬════════════════════════════╬════════════════════════════╬═══════════════════════════════════════════════╡
│ cross-platform ║        USB Key        │     USB/Bluetooth Key      │      USB/Bluetooth Key     │                 USB/Bluetooth Key             │
│ platform       ║  Fingerprint/Face/Pin │ Fingerprint/USB/Bluetooth  │         Fingerprint        │               "Insert security key"           │
└────────────────┴───────────────────────┴────────────────────────────┴────────────────────────────┴───────────────────────────────────────────────┘

遗憾的是,目前对 iOS 的支持仅限于外部验证器。对 iOS 的完全支持确实是阻碍广泛采用的最后一件事,所以祈祷 iOS 14 将提供所需的功能。

它在 iOS 13.3 发行说明中得到了简短的提及:

https://developer.apple.com/documentation/ios_ipados_release_notes/ios_ipados_13_3_release_notes

ETA 这将很快到来:

https://developer.apple.com/videos/play/wwdc2020/10670/

chrome 将不支持任何扩展:

https://bugs.chromium.org/p/chromium/issues/detail?id=1097972

Chromium 团队请求 iOS 13,14

支持 WebAuth

https://bugs.chromium.org/p/chromium/issues/detail?id=1101804

2020 年 10 月 19 日,Apple 发布了他们对 WebAuthn 的解释:https://webkit.org/blog/11312/meet-face-id-and-touch-id-for-the-web/

从 iOS 14 和 macOS Big Sur 开始支持 FaceID 和 TouchID。 要使其正常工作,对于作为平台身份验证器的每个 allowCredentials 条目,您需要添加 transport: ["internal"],否则将继续提示输入 USB/NFC 令牌。

本质上,这:

const publicKeyCredentialRequestOptions = {
    challenge: challengeBuffer,
    allowCredentials: [{
        id: 'credentialsIdentifierOne', // Windows Hello
        type: 'public-key'
    }, {
        id: 'credentialsIdentifierTwo', // iOS FaceID
        type: 'public-key'
    }],
    timeout: 60000
}

变成这样:

const publicKeyCredentialRequestOptions = {
    challenge: challengeBuffer,
    allowCredentials: [{
        id: 'credentialsIdentifierOne', // Windows Hello
        type: 'public-key',
        transports: ["internal"]
    }, {
        id: 'credentialsIdentifierTwo', // iOS FaceID
        type: 'public-key',
        transports: ["internal"]
    }],
    timeout: 60000
}

总的来说,这与 specs 一致,您 应该 能够通过调用 .getTransports() 检索身份验证器的传输列表AuthenticatorResponse。这在教程中没有广泛记录,甚至没有得到广泛支持,所以要小心:

设置跨平台身份验证器时,returned 值通常只包含使用的传输方式,而不是身份验证器支持的所有传输方式。例如,YubiKey 5 NFC 仅在插入时使用 return ["usb"]

因此,您应该避免为这些身份验证器一起设置 transports,或者将它们设置为所有“非内部”传输:["usb", "nfc", "ble"].

至于调用.getTransports(),检查是否可用(2020年12月,Safari仍然没有),如果不可用,则回退根据您何时请求平台身份验证器或跨平台身份验证器来适当transports

另一个非常重要的点:如果你在你的应用程序中启动 SFSafariWebView 来处理这个问题,无论是 PWA、Cordova 还是本机,它都会意外失败。原因? Apple 决定在将 FaceID 作为选项提供给用户之前需要用户激活 (click/tap)。更糟糕的是,您不知道身份验证肯定会失败 - iOS 看起来一切都是 运行 正确,甚至提示用户插入他们的身份验证器,同时知道没有这样的身份验证器存在(凭据 ID 指向 iOS 知道的 FaceID)。

上述问题的解决方案是添加一个额外的步骤并通过要求用户在调用 WebAuthn 代码之前按下按钮来中断身份验证流程。

对我来说,来自 .Net 的 WebAuthn 是一个完整的编码转换噩梦!然而,我终于让它工作了,但后来遇到了 iOS 的问题。最后,一旦我弄清楚 Mac 和 iOS 在我设置 AuthenticatorAttachment 时都不喜欢它是怎么回事,就我而言,修复是一个简单的修复。因此,我最终不得不使用从这里获得的函数来检测 OS:

然后我编码出来如下:

   var os = getOS();
   if (os == 'iOS' || os =='Mac OS') {
      credentialOptions.authenticatorSelection.authenticatorAttachment = undefined;
   }