繁体   English   中英

FIDO2 跨设备无缝登录 - 密钥

[英]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 跨设备身份验证流程,

是的,这正是我想要实现的。 我现在已经回滚到: -

  1. 在我的 Android 手机上启用了蓝牙
  2. 蓝牙可见
  3. 登录PC/Chrome和手机谷歌账户
  4. 为我的 windows 帐户设置 Windows 你好 PIN

但是下面的所有代码给我的是输入我的 PIN 码的选项“添加新的 Android 手机”

“你在这里混合了一些不同的东西。安全密钥、本地平台身份验证器 (Windows Hello) 和你的手机都将拥有自己的凭据。”

我确定你是对的。 我只是在拉动我所知道的所有离职人员以使其发挥作用:- Windows 电话链接、Account.Live.Com 帐户选项等

不需要居民凭据(尚不支持)并且不设置附件首选项。

不确定那是什么意思。 如果您的意思是 USB 密钥,那很好,我不想使用它,但我收到了提示。 (见下文)

在 Chrome 中出现提示时,添加您的手机以链接它,扫描手机上的 QR,然后执行 UV 手势。

好的,你用的是什么二维码阅读器?

我的问题是 Chrome 没有提示我添加电话:-( 我缺少配置或 API 参数?

请帮忙。

编辑结束

我理解“今年晚些时候可供开发人员使用”的警告,但作为 FIDO 的拥护者,我对Passkeys 9:00+的预览功能感到非常兴奋。 当前版本的 Chrome/Samsung/Windows 的潜在支持进一步激发了我的胃口!

TL;博士

  1. 我已将三星/Android 手机与我的 Windows PC 配对
  2. 我启用了我的 Yubikey USB设备(没有 Yubikey 软件)
  3. 我打电话给 navigator.credentials.create 和 Windows 提示我输入我的 PIN
  4. 然后我打电话给 navigator.credentials.get 和 Windows 告诉我它不认识我的 YubiKey 坏 USB
  5. 取消后,系统会提示我使用替代设备设备
  6. 如果我选择我的 SM_* 手机,我的手机会提示我输入指纹,三星/Android 很高兴!
  7. 铬不是不是 快乐的

因此,尽管我愿意承认/承认这是“新兴”技术:-

  1. 为什么 Create 提示输入 PIN 而不是指纹
  2. 我尝试设置各种 Google 帐户选项和 Windows Live 选项和 Windows/Accounts 选项; 哪些在玩?
  3. 我的手机已与 Windows/蓝牙配对; 这对 Chrome 来说还不够吗?
  4. 如果我选择“添加新的 Android 手机”,我会得到恐龙二维码。 在我的手机上,三星浏览器是我唯一返回 FIDO:/484543913687778941263973123987003762051850670080716404329165 的 QRC 阅读器。 . . Chrome 无法识别它; go 在哪里?
  5. 这是 Android/Samsumg 提示我的生物识别

请参阅下面的源代码。

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.

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