[英]FIDO2 seamless sign-in across devices - Passkeys
EDIT 2编辑 2
Just to ellaborate on what @Tim has already explained, I made these changes to the credential.create Authenticator Selection Options: -只是为了详细说明@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"
},
Apart from the first time it still prompting for USB dongle, it works like a dream!除了第一次还是提示USB dongle,简直如梦如幻!
It even turns on BlueTooth if you've forgotten.如果您忘记了,它甚至会打开蓝牙。 Wow?
哇? (How does it know my phone in this case? 'Cos I'm logged on with the same Chrome account PC & Phone? Some registry?)
(在这种情况下它是如何知道我的手机的?“因为我使用相同的 Chrome 帐户 PC 和电话登录?一些注册表?)
Anyway this functionality is just the mutt's nuts.无论如何,这个功能只是笨蛋的坚果。 I have tried to drag sites in Perth Western Australia kicking and screaming to FIDO2 but this has to be the clincher.
我曾试图将珀斯西澳大利亚的站点拖到 FIDO2 上,但这必须是关键。
Well done to all involved!干得好所有相关人员!
EDIT 2 END编辑 2 结束
Edit Start
编辑开始
If you are just trying to test the new FIDO cross device authentication flow using your phone,如果您只是尝试使用手机测试新的 FIDO 跨设备身份验证流程,
Yes that is exactly what I'm trying to achieve.是的,这正是我想要实现的。 I have now rolled back to just: -
我现在已经回滚到: -
But all the bellow code gives me is the option to enter my PIN no "Add a new Android phone"但是下面的所有代码给我的是输入我的 PIN 码的选项“添加新的 Android 手机”
"You are mixing a few different things here. The security key, local platform authenticator (Windows Hello) and your phone will all have their own credential." “你在这里混合了一些不同的东西。安全密钥、本地平台身份验证器 (Windows Hello) 和你的手机都将拥有自己的凭据。”
I'm sure you're correct.我确定你是对的。 I was just pulling all the leavers I knew trying to make it work:- Windows Phone Link, Acccount.Live.Com account options, etc
我只是在拉动我所知道的所有离职人员以使其发挥作用:- Windows 电话链接、Account.Live.Com 帐户选项等
do not require a resident credential (not yet supported) and do not set an attachment preference.不需要居民凭据(尚不支持)并且不设置附件首选项。
Not sure what that means.不确定那是什么意思。 If you mean the USB key then fine I don't want to use it, but I was getting prompted for it.
如果您的意思是 USB 密钥,那很好,我不想使用它,但我收到了提示。 (See below)
(见下文)
When prompted in Chrome, add your phone to link it, scan the QR on your phone and then perform the UV gesture.在 Chrome 中出现提示时,添加您的手机以链接它,扫描手机上的 QR,然后执行 UV 手势。
Ok, what QR code reader are you using?好的,你用的是什么二维码阅读器?
My problem is Chrome is not prompting me to add a phone:-( There's a configuration or API argument I'm missing?我的问题是 Chrome 没有提示我添加电话:-( 我缺少配置或 API 参数?
Please help.请帮忙。
Edit End
编辑结束
I understand the "available for developers later this year" caveat, but as a FIDO devotee I have been very excited about the previewed functionality from Passkeys 9:00+ .我理解“今年晚些时候可供开发人员使用”的警告,但作为 FIDO 的拥护者,我对Passkeys 9:00+的预览功能感到非常兴奋。 My appetite has been further whetted by the latent support in the current version of Chrome/Samsung/Windows!
当前版本的 Chrome/Samsung/Windows 的潜在支持进一步激发了我的胃口!
TL;DR TL;博士
So while I willing acknowledge/concede this is "emerging" technology: -因此,尽管我愿意承认/承认这是“新兴”技术:-
Please see source code below.请参阅下面的源代码。
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)));
}
You can find helpful information about FIDO and Passkeys at passkeys.com .I used it and it took me no time to implement FIDO into my website您可以在 passkeys.com 找到有关 FIDO 和Passkeys的有用信息。我使用了它,很快就将 FIDO 实施到我的网站中
You are mixing a few different things here.你在这里混合了一些不同的东西。 The security key, local platform authenticator (Windows Hello) and your phone will all have their own credential.
安全密钥、本地平台身份验证器 (Windows Hello) 和您的手机都将拥有自己的凭据。
If you are just trying to test the new FIDO cross device authentication flow using your phone, do not require a resident credential (not yet supported) and do not set an attachment preference.如果您只是尝试使用手机测试新的 FIDO 跨设备身份验证流程,则不需要常驻凭据(尚不支持)并且不要设置附件首选项。
When prompted in Chrome, add your phone to link it, scan the QR on your phone and then perform the UV gesture.在 Chrome 中出现提示时,添加您的手机以链接它,扫描手机上的 QR,然后执行 UV 手势。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.