【问题标题】:Exception from WebAuthn Authentication API with Yubikey来自 Yubikey 的 WebAuthn 身份验证 API 的异常
【发布时间】:2021-02-08 10:23:56
【问题描述】:

我正在为新创建的网站添加 WebAuthn 支持,但在 navigator.credentials.get() 调用期间遇到了问题。客户端是 Fedora 33 上的 Firefox 85.0。如果重要,服务器是 Fedora 33 上的 Apache httpd。令牌是 Yubikey 4 或 Yubikey 5NFC(结果相同)。这是进行 API 调用的函数。显然,这里硬编码的凭证 ID 用于测试,而不是最终产品的一部分:

function handleUserAuthenticationResponse(r) {
  var cid1 = {type: "public-key", id: base64ToArrayBuffer("gL0Ig10uA2tn8L0kn2L9FoGqIPSrqvc1lLBwgQhcVDa200b1P94kPv94T6O1bDZyYRrfLbTrLRsubDxuYUxHCg==")};
  var cid2 = {type: "public-key", id: base64ToArrayBuffer("tjW1RPqtAJm69I/qeV7eRFJx6h87J3NPeJ/hhbkjttcCc2BWHQ2v2nueoKBSGabw1eYsT8S+lhJv1l1mYWX+Uw==")};
  var options = {
    rpID: "http://localhost",
    challenge: base64ToArrayBuffer(r.challenge),
    allowCredentials: [cid1,cid2],
    timeout: 60000
  };

  if (!window.PublicKeyCredential) {
    throw new Error("Unable to access credentials interface");
  }
  navigator.credentials.get({"publicKey":options})
    .then(assertion => handleTokenAssertion(assertion))
    .catch(e => {console.log("Error fetching token assertion:",e);});
}
function base64ToArrayBuffer(base64) {
    var binary_string = window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}
function handleTokenAssertion(a) {
  alert("Got an assertion!");
}

一切似乎都正常,Yubikey LED 闪烁,我按下触摸板,但随后我得到一个异常:

Error fetching token assertion: DOMException: An attempt was made to use an object that is not, or is no longer, usable

这似乎有点像 Firefox 的包罗万象。它可能表明令牌与 allowedCredentials[] 之一或其他内容不匹配。很难说。 Yubikey 上的 FIDO2 凭证是使用与 libfido2 源打包的 fido2-cred(1) 工具创建的。在这种情况下, credentialId 来自fido2-cred -M 输出:

CuCEGL10uPhBmNCY4NsGaAz0gir/68UMGFQn0pfb6tc=
http://localhost
fido-u2f
WMSGBbi6CMINQvnkVRUYcYltDg3pgFlihvtzbRHuwBPipEEAAAAAAAAAAAAAAAAAAAAAAAAAAABAgL0Ig10uA2tn8L0kn2L9FoGqIPSrqvc1lLBwgQhcVDa200b1P94kPv94T6O1bDZyYRrfLbTrLRsubDxuYUxHCqUBAgMmIAEhWCA5itRRCBO0lnsztvPvI1waVZLBCZ1XMJjOvlN2oZmBCyJYILFaRjThs5Paj1sOp81iID1LpUBYHJhp4dizC0eI/RrE
gL0Ig10uA2tn8L0kn2L9FoGqIPSrqvc1lLBwgQhcVDa200b1P94kPv94T6O1bDZyYRrfLbTrLRsubDxuYUxHCg==
MEQCIFfs8PagKhNnDgzxfurVzdkTDVTT6ixKk0ak/2qrbSPUAiAf64w390rX1cyY58JgSC/Ac97w6TLcYKuqxOSn5lxV0g==
<long assertion certificate>

您可以在第 5 行看到 credentialId,它与 Javascript 函数中的 cid1 匹配。此外,如果我使用此 credentialId 从令牌请求断言,并且所有其他内容与 fido2-assert -G 相同(挑战除外),一切正常:我得到断言并使用 fido2-assert -V 正确验证。

如果没有更有意义的诊断,很难知道该尝试什么,所以我想我会在这里问一下,看看是否有人有任何提示。也许我在使用 Javascript 或凭据 API 时犯了一些基本错误?

谢谢!

更新:我认为值得尝试的一种可能性是从 RP ID 中删除该方案,但这没有任何区别。

更新:查看 firefox 源代码,错误显然是 NS_ERROR_DOM_INVALID_STATE_ERR,它涵盖了几种不同的情况,但在这种情况下很可能是 U2F_ERROR_INVALID_STATE 的翻译(在 dom/webauthn/U2FHIDTokenManager.h 中)。反过来,U2F_ERROR_INVALID_STATE 在 third_party/rust/authenticator/src/u2fhid-capi.h 中定义为一个简单的数值 (3),没有说明该值的来源。也许它是由 Yubikey 的底层 HID 驱动程序定义的,但不清楚对应的驱动程序是什么。狩猎仍在继续……

【问题讨论】:

    标签: javascript webauthn yubico


    【解决方案1】:

    事实证明,问题确实是依赖方 ID 的格式。基于来自网络的示例代码(可能与其他浏览器或代码版本一起使用?),我最初使用完整的 scheme://domain 格式作为 rpID(所以在我上面的代码中,http://localhost),但是事实证明,所需要的只是域 (localhost)。以这种方式修改 rpID 可以让断言过程成功。

    最初我认为这不起作用,但结果证明我只是忘记提交更改。姗姗来迟,它的工作原理。

    【讨论】:

      猜你喜欢
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      • 2022-07-19
      • 1970-01-01
      • 2019-09-18
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多