简体   繁体   English

FIDO2 跨设备无缝登录 - 密钥

[英]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: -我现在已经回滚到: -

  1. Bluetooth enabled on my Android phone在我的 Android 手机上启用了蓝牙
  2. Bluetooth visible蓝牙可见
  3. Logged in to Google account both PC/Chrome and Phone登录PC/Chrome和手机谷歌账户
  4. Windows hello PIN set for my windows account为我的 windows 帐户设置 Windows 你好 PIN

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;博士

  1. I have paired my Samsung/Android phone with my Windows PC我已将三星/Android 手机与我的 Windows PC 配对
  2. I have enabled my Yubikey USB device (without Yubikey software)我启用了我的 Yubikey USB设备(没有 Yubikey 软件)
  3. I call navigator.credentials.create and Windows prompts me for my PIN我打电话给 navigator.credentials.create 和 Windows 提示我输入我的 PIN
  4. I then call navigator.credentials.get and Windows tells me that it doesn't recognize my YubiKey然后我打电话给 navigator.credentials.get 和 Windows 告诉我它不认识我的 YubiKey 坏 USB
  5. On Cancel, I am then prompted for an alternative device取消后,系统会提示我使用替代设备设备
  6. If I choose my SM_* phone my phone prompts me for my finger print and Samsung/Android is happy!如果我选择我的 SM_* 手机,我的手机会提示我输入指纹,三星/Android 很高兴!
  7. Chrome is NOT铬不是不是 happy快乐的

So while I willing acknowledge/concede this is "emerging" technology: -因此,尽管我愿意承认/承认这是“新兴”技术:-

  1. Why does Create prompt for a PIN and not a fingerprint为什么 Create 提示输入 PIN 而不是指纹
  2. I've tried setting various Google account options and Windows Live options and Windows/Accounts options;我尝试设置各种 Google 帐户选项和 Windows Live 选项和 Windows/Accounts 选项; which are in play?哪些在玩?
  3. My phone is paired with Windows/Bluetooth;我的手机已与 Windows/蓝牙配对; is this not enough for Chrome?这对 Chrome 来说还不够吗?
  4. If I choose "Add a new Android phone" I get the dinosaur QRCode.如果我选择“添加新的 Android 手机”,我会得到恐龙二维码。 On my phone Samsung browser is my only QRC reader which returns FIDO:/484543913687778941263973123987003762051850670080716404329165.在我的手机上,三星浏览器是我唯一返回 FIDO:/484543913687778941263973123987003762051850670080716404329165 的 QRC 阅读器。 . . . . Chrome does not recognize it; Chrome 无法识别它; where does it go? go 在哪里?
  5. Here is Android/Samsumg prompting me for my这是 Android/Samsumg 提示我的生物识别

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM