首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨设备的FIDO2无缝登录.密码

跨设备的FIDO2无缝登录.密码
EN

Stack Overflow用户
提问于 2022-07-23 07:13:31
回答 1查看 383关注 0票数 0

编辑2

为了不了解@Tim已经解释过的内容,我对credential.create身份验证器选择选项做了以下更改:-

代码语言:javascript
复制
    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,它的工作就像一个梦!

如果你忘记了,它甚至会打开BlueTooth。哇!(在这种情况下,它怎么知道我的手机?因为我用相同的Chrome帐户PC和Phone登录?注册?)

不管怎么说,这个功能只是狗的坚果!我试着把位于西澳大利亚珀斯的网站拖到FIDO2上,但这一定是最重要的。

对所有相关的人都做得好!

编辑2端

编辑启动

如果您只是尝试使用您的手机测试新的FIDO跨设备身份验证流,

是的,这正是我想要达到的目标。我现在回过头来说:

  1. 蓝牙在我的Android手机上启用
  2. 蓝牙可见
  3. 登录到谷歌个人电脑/Chrome和手机帐户
  4. 为我的Windows帐户设置了windows hello PIN

但是下面的代码给了我选择输入我的PIN no“添加一个新的Android手机”

“您在这里混合了几个不同的东西,安全密钥、本地平台身份验证器(Windows )和您的手机都将拥有自己的证书。”

我肯定你是对的。我只是想把所有我认识的离校者都拉出来让它正常工作:- Windows,Acccount.Live.Com帐户选项,等等

不需要常驻凭证(还不支持),也不需要设置附件首选项。

不知道那是什么意思。如果你指的是USB键,那么很好,我不想使用它,但我被提示要使用它。(见下文)

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

好的,您使用的是什么QR代码阅读器?

我的问题是Chrome并没有促使我添加一部手机:-(我缺少一个配置或API参数?)

请帮帮忙。

编辑端

我理解“今年晚些时候为开发人员提供的”警告,但作为一个FIDO爱好者,我对密码9:00+预览的功能感到非常兴奋。现在Chrome/Samsung/Windows版本的潜在支持进一步刺激了我的胃口!

TL;DR

  1. 我已经把我的三星/安卓手机和我的Windows配对了
  2. 我启用了我的Yubikey USB设备(没有Yubikey软件)
  3. 我打电话给navigator.credentials.create,Windows会提示我输入密码
  4. 然后我打电话给navigator.credentials.get,Windows告诉我它不认识我的YubiKey

  1. 在取消时,我会被提示要另一个设备。

  1. 如果我选择我的SM_*手机,我的手机提示我的手指指纹,三星/安卓是快乐的!
  2. 铬不是

高兴的

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

  1. 为什么要为PIN而不是指纹创建提示
  2. 我尝试过设置各种Google帐户选项、和Windows / account选项;哪些在发挥作用?
  3. 我的手机配上了Windows/蓝牙,这对Chrome来说还不够吗?
  4. 如果我选择“添加一个新的安卓手机”,我会得到恐龙QRCode。在我的手机上,三星浏览器是我唯一返回FIDO:/484543913687778941263973123987003762051850670080716404329165的QRC阅读器。。。Chrome不认识它,它去哪里了?
  5. 这是Android/Samsumg给我的提示

请参阅下面的源代码。

代码语言:javascript
复制
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)));
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-25 13:12:22

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

如果您只是尝试使用您的手机测试新的FIDO跨设备身份验证流,则不需要常驻凭证(还不支持),也不要设置附件首选项。

当提示进入Chrome,添加您的手机连接它,扫描你的手机上的QR,然后执行紫外线手势。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73088756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档