我正在为一个新创建的网站添加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或credentials API上犯了一些基本的错误?
谢谢!
更新:我认为可能值得尝试的一种可能性是从RP ID中删除该方案,但这并没有什么不同。
更新:查看火狐的源代码,错误显然是NS_ERROR_DOM_INVALID_STATE_ERR,它涵盖了几种不同的情况,但在这种情况下,很可能是U2F_ERROR_INVALID_STATE的翻译(在dom/webauthn/U2FHIDTokenManager.h中)。反过来,在third_party/rust/authenticator/src/u2fhid-capi.h中,U2F_ERROR_INVALID_STATE被定义为一个简单的数值(3),没有指明该值来自何处。也许它是由Yubikey的底层HID驱动程序定义的,但不清楚它对应的是什么驱动程序。追捕仍在继续..。
发布于 2021-02-09 15:55:47
基于net上的示例代码(它可能适用于其他浏览器或代码版本?),我最初使用完整的方案:// rpID格式(所以在上面的代码中是http://localhost),但结果是只需要域(localhost)。以这种方式修改rpID可以使断言过程成功。
最初我认为这不起作用,但事实证明我只是忘记了提交更改。虽然做得太迟了,但还是奏效了。
https://stackoverflow.com/questions/66099755
复制相似问题