[英]FIDO2 seamless sign-in across devices - Passkeys
编辑 2
只是为了详细说明@Tim 已经解释过的内容,我对 credential.create Authenticator 选择选项进行了这些更改:-
authenticatorSelection: {
//This defaults to false but I specified it anyway
requireResidentKey: false,
//This defaults to "preferred" and gives a warning in Chrome if not specified.
//Not sure if it has any functional impact
userVerification: "discouraged",
//This was required to get it to work
authenticatorAttachment: "cross-platform"
},
除了第一次还是提示USB dongle,简直如梦如幻!
如果您忘记了,它甚至会打开蓝牙。 哇? (在这种情况下它是如何知道我的手机的?“因为我使用相同的 Chrome 帐户 PC 和电话登录?一些注册表?)
无论如何,这个功能只是笨蛋的坚果。 我曾试图将珀斯西澳大利亚的站点拖到 FIDO2 上,但这必须是关键。
干得好所有相关人员!
编辑 2 结束
编辑开始
如果您只是尝试使用手机测试新的 FIDO 跨设备身份验证流程,
是的,这正是我想要实现的。 我现在已经回滚到: -
但是下面的所有代码给我的是输入我的 PIN 码的选项“添加新的 Android 手机”
“你在这里混合了一些不同的东西。安全密钥、本地平台身份验证器 (Windows Hello) 和你的手机都将拥有自己的凭据。”
我确定你是对的。 我只是在拉动我所知道的所有离职人员以使其发挥作用:- Windows 电话链接、Account.Live.Com 帐户选项等
不需要居民凭据(尚不支持)并且不设置附件首选项。
不确定那是什么意思。 如果您的意思是 USB 密钥,那很好,我不想使用它,但我收到了提示。 (见下文)
在 Chrome 中出现提示时,添加您的手机以链接它,扫描手机上的 QR,然后执行 UV 手势。
好的,你用的是什么二维码阅读器?
我的问题是 Chrome 没有提示我添加电话:-( 我缺少配置或 API 参数?
请帮忙。
编辑结束
我理解“今年晚些时候可供开发人员使用”的警告,但作为 FIDO 的拥护者,我对Passkeys 9:00+的预览功能感到非常兴奋。 当前版本的 Chrome/Samsung/Windows 的潜在支持进一步激发了我的胃口!
TL;博士
因此,尽管我愿意承认/承认这是“新兴”技术:-
请参阅下面的源代码。
const utf8Decoder = new TextDecoder('utf-8');
async function verifyCredential() {
var keyResult = await getKey();
var serverChallenge = JSON.parse(keyResult);
var credentialId = localStorage.getItem("credentialId");
if (!credentialId) {
throw new Error("You must create a Credential first");
}
var allowCredentials = [{
type: "public-key",
id: Uint8Array.from(atob(credentialId), x => x.charCodeAt(0)).buffer
}]
var getAssertionOptions = {
timeout: 30000,
challenge: Uint8Array.from(serverChallenge.Token, c => c.charCodeAt(0)).buffer,
allowCredentials: allowCredentials,
userVerification: "required"
};
return navigator.credentials.get({
publicKey: getAssertionOptions
}).then(rawAssertion => {
var assertion = {
id: base64encode(rawAssertion.rawId),
clientDataJSON: utf8Decoder.decode(rawAssertion.response.clientDataJSON),
userHandle: base64encode(rawAssertion.response.userHandle),
signature: base64encode(rawAssertion.response.signature),
authenticatorData: base64encode(rawAssertion.response.authenticatorData)
};
// Check id = allowcredentials.id
console.log("=== Assertion response ===");
console.log(assertion);
verifyAssertion(assertion).then(
result => {
var res = JSON.parse(result);
console.log(res.success);
if (res.success) {
}
});
return;
}).catch(
(err) => {
if (err.name == "NotAllowedError") {
console.log("here " + err.name);
} else {
console.log("other " + err.name);
}
return Promise.resolve(false);
});
}
async function createCredential() {
var keyResult = await getKey();
var serverChallenge = JSON.parse(keyResult);
var createCredentialOptions = {
rp: {
name: "WebAuthn Sample App",
icon: ""
},
user: {
id: Uint8Array.from("some.user.guid", c => c.charCodeAt(0)),
name: "maherrj@gmail.com",
displayName: "Richard Maher",
icon: ""
},
pubKeyCredParams: [
{
//External authenticators support the ES256 algorithm
type: "public-key",
alg: -7
},
{
//Windows Hello supports the RS256 algorithm
type: "public-key",
alg: -257
}
],
authenticatorSelection: {
//Select authenticators that support username-less flows
//requireResidentKey: true,
//Select authenticators that have a second factor (e.g. PIN, Bio) "preferred" "discouraged"
userVerification: "required",
//Selects between bound or detachable authenticators
authenticatorAttachment: "platform" // Optional
},
//Since Edge shows UI, it is better to select larger timeout values
timeout: 30000,
//an opaque challenge that the authenticator signs over
challenge: Uint8Array.from(serverChallenge.Token, c => c.charCodeAt(0)).buffer,
//prevent re-registration by specifying existing credentials here
excludeCredentials: [],
//specifies whether you need an attestation statement
attestation: "none"
};
const authAbort = new AbortController();
const abortSignal = authAbort.signal;
abortSignal.addEventListener("abort", (e) => { console.log("It has been aborted"); });
return navigator.credentials.create({
publicKey: createCredentialOptions,
signal: abortSignal
}).then(rawAttestation => {
var attestation = {
id: base64encode(rawAttestation.rawId),
clientDataJSON: utf8Decoder.decode(rawAttestation.response.clientDataJSON),
attestationObject: base64encode(rawAttestation.response.attestationObject)
};
console.log("=== Attestation response ===");
console.log(attestation);
verifyCredentials(attestation).then(
result => {
var res = JSON.parse(result);
console.log(res.success);
if (res.success) {
localStorage.setItem("credentialId", res.id);
}
});
return;
}).catch(
(err) => {
if (err.name == "NotAllowedError") {
console.log("here " + err.name);
} else {
console.log("other " + err.name);
}
return Promise.resolve(false);
});
}
async function verifyCredentials(attestation) {
let params = JSON.stringify(attestation);
let resp = await fetch("api/fido/verifycredentials", {
method: "POST",
headers: { "Content-type": "application/json", "Accept": "application/json" },
body: params
});
var myStat;
if (resp.ok) {
myStat = await resp.json();
console.log("Stat vc = " + myStat)
} else {
console.log("boom");
}
console.log("done ");
return myStat;
}
async function verifyAssertion(assertion) {
let params = JSON.stringify(assertion);
let resp = await fetch("api/fido/verifyassertion", {
method: "POST",
headers: { "Content-type": "application/json", "Accept": "application/json" },
body: params
});
var myStat;
if (resp.ok) {
myStat = await resp.json();
console.log("Stat va = " + myStat)
} else {
console.log("boom");
}
console.log("done ");
return myStat;
}
async function getKey() {
let resp = await fetch("api/fido/getkey", {
method: "GET",
headers: { "Content-type": "application/json", "Accept": "application/json" }
});
var mykey;
if (resp.ok) {
mykey = await resp.json();
console.log("key = " + mykey)
} else {
throw new Error("boom");
}
console.log("done key");
return mykey;
}
function base64encode(arrayBuffer) {
if (!arrayBuffer || arrayBuffer.length == 0)
return undefined;
return btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
}
您可以在 passkeys.com 找到有关 FIDO 和Passkeys的有用信息。我使用了它,很快就将 FIDO 实施到我的网站中
你在这里混合了一些不同的东西。 安全密钥、本地平台身份验证器 (Windows Hello) 和您的手机都将拥有自己的凭据。
如果您只是尝试使用手机测试新的 FIDO 跨设备身份验证流程,则不需要常驻凭据(尚不支持)并且不要设置附件首选项。
在 Chrome 中出现提示时,添加您的手机以链接它,扫描手机上的 QR,然后执行 UV 手势。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.