如何使用FIDO U2F允许用户对我的网站进行身份验证?

时间:2022-09-11 11:36:37

With all the recent buzz around the FIDO U2F specification, I would like to implement FIDO U2F test-wise on a testbed to be ready for the forthcoming roll out of the final specification.

在最近关于FIDO U2F规范的讨论中,我希望在测试台上实现FIDO U2F,以便为即将推出的最终规范做好准备。

So far, I have a FIDO U2F security key produced by Yubico and the FIDO U2F (Universal 2nd Factor) extension installed in Chrome. I have also managed to set up the security key to work with my Google log-in.

到目前为止,我有一个FIDO U2F安全密钥由Yubico和FIDO U2F(通用第二因子)扩展安装在Chrome中。我还成功地设置了使用谷歌登录的安全密钥。

Now, I'm not sure how to make use of this stuff for my own site. I have looked through Google's Github page for the U2F project and I have checked their web app front-end. It looks really simple (JavaScript only). So is implementing second factor auth with FIDO as simple as implementing a few JavaScript calls? All that seems to be happening for the registration in the example is this:

现在,我不知道如何利用这些东西为我自己的网站。我查看了谷歌的Github页面,了解了U2F项目,并查看了他们的web应用前端。它看起来非常简单(仅适用于JavaScript)。那么,用FIDO来实现第二个因子auth是否就像实现几个JavaScript调用一样简单呢?在这个例子中,注册的情况是这样的:

      var registerRequest = {
            appId: enrollData.appId,
            challenge: enrollData.challenge,
            version: enrollData.version
      };

      u2f.register([registerRequest], [], function (result) {
          if (result.errorCode) {
        document.getElementById('status')
          .innerHTML = "Failed. Error code: " + result.errorCode;
        return;
          }
          document.location = "/enrollFinish"
          + "?browserData=" + result.clientData
          + "&enrollData=" + result.registrationData
          + "&challenge=" + enrollData.challenge
          + "&sessionId=" + enrollData.sessionId;             
      });

But how can I use that for an implementation myself? Will I be able to use the callback from this method call for the user registration?

但是我如何将它用于实现呢?我可以使用这个方法调用的回调来进行用户注册吗?

2 个解决方案

#1


42  

What you are trying to do is implement a so called "relying party", meaning that your web service will rely on the identity assertion provided by the FIDO U2F token.

您正在尝试实现所谓的“依赖方”,这意味着您的web服务将依赖FIDO U2F令牌提供的标识断言。

You will need to understand the U2F specifications to do that. Especially how the challenge-response paradigm is to be implemented and how app ids and facets work. This is described in the spec in detail.

要做到这一点,您需要了解U2F规范。特别是如何实现挑战-响应范式,以及如何使用应用程序id和facet。这在规范中有详细描述。

You are right: The actual code necessary to work with FIDO U2F from the front end of you application is almost trivial (that is, if you use the "high-level" JavaScript API as opposed to the "low-level" MessagePort API). Your application will however need to work with the messages generated by the token and validate them. This is not trivial.

您是对的:在应用程序前端使用FIDO U2F所需的实际代码几乎是微不足道的(也就是说,如果您使用“高级”JavaScript API而不是“低级”MessagePort API)。但是,您的应用程序需要使用令牌生成的消息并对它们进行验证。这不是微不足道的。

To illustrate how you could pursue implementing a relying party site, I will give a few code examples, taken from a Virtual FIDO U2F Token Extension that I have programmed lately for academic reasons. You can see the page for the full example code.

为了说明如何实现依赖方站点,我将给出一些代码示例,这些示例来自一个虚拟FIDO U2F令牌扩展,我最近出于学术原因编写了这个扩展。您可以在页面上看到完整的示例代码。


Before your users can use their FIDO U2F tokens to authenticate, they need to register it with you. In order to allow them to do so, you need to call window.u2f.register in their browser. To do that, you need to provide a few parameters (again; read the spec for details). Among them a challenge and the id of your app. For a web app, this id must be the web origin of the web page triggering the FIDO operation. Let's assume it is example.org:

在用户可以使用他们的FIDO U2F令牌进行身份验证之前,他们需要向您注册它。为了允许他们这样做,您需要调用windows .u2f。登记在他们的浏览器。为此,您需要提供一些参数(再次;详细阅读说明书)。其中一个是挑战和你的应用的id。对于一个web应用,这个id必须是触发FIDO操作的web页面的web来源。假设它是example.org。

window.u2f.register([
    {
        version : "U2F_V2",
        challenge : "YXJlIHlvdSBib3JlZD8gOy0p",
        appId : "http://example.org",
        sessionId : "26"
    }
], [], function (data) {

});

Once the user performs a "user presence test" (e.g. by touching the token), you will receive a response, which is a JSON object (see spec for more details)

一旦用户执行“用户状态测试”(例如,通过触摸令牌),您将收到一个响应,这是一个JSON对象(详细信息请参阅spec)

dictionary RegisterResponse {
    DOMString registrationData;
    DOMString clientData;
};

This data contains several elements that your application needs to work with.

此数据包含应用程序需要处理的几个元素。

如何使用FIDO U2F允许用户对我的网站进行身份验证?

  1. The public key of the generated key pair -- You need to store this for future authentication use.
  2. 生成的密钥对的公钥——您需要将它存储起来以供将来的身份验证使用。
  3. The key handle of the generated key pair -- You also need to store this for future use.
  4. 生成的密钥对的密钥句柄——您还需要存储它以备将来使用。
  5. The certificate -- You need to check whether you trust this certificate and the CA.
  6. 证书——您需要检查您是否信任这个证书和CA。
  7. The signature -- You need to check whether the signature is valid (i.e. confirms to the key stored with the certificate) and whether the data signed is the data expected.
  8. 签名——您需要检查签名是否有效(例如,向存储在证书中的密钥进行确认),以及所签署的数据是否为预期的数据。

I have prepared a rough implementation draft for the relying party server in Java that shows how to extract and validate this information lately.

我为Java中的依赖方服务器准备了一个粗略的实现草案,展示了如何提取和验证这些信息。


Once the registration is complete and you have somehow stored the details of the generated key, you can sign requests.

一旦注册完成,并且您以某种方式存储了生成的密钥的细节,您就可以对请求进行签名。

As you said, this can be initiated short and sweet through the high-level JavaScript API:

如您所言,这可以通过高级JavaScript API进行快速而甜蜜的启动:

window.u2f.sign([{
    version : "U2F_V2",
    challenge : "c3RpbGwgYm9yZWQ/IQ",
    app_id : "http://example.org",
    sessionId : "42",
    keyHandle: "ZHVtbXlfa2V5X2hhbmRsZQ"
}], function (data) {

});

Here, you need to provide the key handle, you have obtained during registration. Once again, after the user performs a "user presence test" (e.g. by touching the token), you will receive a response, which is a JSON object (again, see spec for more details)

在这里,您需要提供密钥句柄,您在注册时已经获得。再一次,在用户执行“用户存在测试”(例如通过触摸令牌)之后,您将收到一个响应,它是一个JSON对象(同样,更多细节请参见spec)

dictionary SignResponse {
    DOMString keyHandle;
    DOMString signatureData;
    DOMString clientData;
};

You the need to validate the signature data contained herein.

您需要验证本文所包含的签名数据。

如何使用FIDO U2F允许用户对我的网站进行身份验证?

  1. You need to make sure that the signature matches the public key you have obtained before.
  2. 您需要确保签名与您以前获得的公钥匹配。
  3. You also need to validate that the string signed is appropriate.
  4. 您还需要验证签名的字符串是否合适。

Once you have performed these validations, you can consider the user authenticated. A brief example implementation of the server side code for that is also contained in my server example.

一旦执行了这些验证,就可以考虑已验证的用户。服务器端代码的一个简单示例实现也包含在我的服务器示例中。

#2


15  

I have recently written instructions for this, as well as listing all U2F server libraries (most of them bundles a fully working demo server), at developers.yubico.com/U2F. The goal is to enable developers to implement/integrate U2F without having to read the specifications.

我最近为它编写了一些说明,并在developers.yubico.com/U2F上列出了所有U2F服务器库(其中大多数都打包了一个完整的演示服务器)。目标是使开发人员能够实现/集成U2F,而不必阅读规范。

Disclaimer: I work as a developer at Yubico.

免责声明:我是Yubico的一名开发人员。

#1


42  

What you are trying to do is implement a so called "relying party", meaning that your web service will rely on the identity assertion provided by the FIDO U2F token.

您正在尝试实现所谓的“依赖方”,这意味着您的web服务将依赖FIDO U2F令牌提供的标识断言。

You will need to understand the U2F specifications to do that. Especially how the challenge-response paradigm is to be implemented and how app ids and facets work. This is described in the spec in detail.

要做到这一点,您需要了解U2F规范。特别是如何实现挑战-响应范式,以及如何使用应用程序id和facet。这在规范中有详细描述。

You are right: The actual code necessary to work with FIDO U2F from the front end of you application is almost trivial (that is, if you use the "high-level" JavaScript API as opposed to the "low-level" MessagePort API). Your application will however need to work with the messages generated by the token and validate them. This is not trivial.

您是对的:在应用程序前端使用FIDO U2F所需的实际代码几乎是微不足道的(也就是说,如果您使用“高级”JavaScript API而不是“低级”MessagePort API)。但是,您的应用程序需要使用令牌生成的消息并对它们进行验证。这不是微不足道的。

To illustrate how you could pursue implementing a relying party site, I will give a few code examples, taken from a Virtual FIDO U2F Token Extension that I have programmed lately for academic reasons. You can see the page for the full example code.

为了说明如何实现依赖方站点,我将给出一些代码示例,这些示例来自一个虚拟FIDO U2F令牌扩展,我最近出于学术原因编写了这个扩展。您可以在页面上看到完整的示例代码。


Before your users can use their FIDO U2F tokens to authenticate, they need to register it with you. In order to allow them to do so, you need to call window.u2f.register in their browser. To do that, you need to provide a few parameters (again; read the spec for details). Among them a challenge and the id of your app. For a web app, this id must be the web origin of the web page triggering the FIDO operation. Let's assume it is example.org:

在用户可以使用他们的FIDO U2F令牌进行身份验证之前,他们需要向您注册它。为了允许他们这样做,您需要调用windows .u2f。登记在他们的浏览器。为此,您需要提供一些参数(再次;详细阅读说明书)。其中一个是挑战和你的应用的id。对于一个web应用,这个id必须是触发FIDO操作的web页面的web来源。假设它是example.org。

window.u2f.register([
    {
        version : "U2F_V2",
        challenge : "YXJlIHlvdSBib3JlZD8gOy0p",
        appId : "http://example.org",
        sessionId : "26"
    }
], [], function (data) {

});

Once the user performs a "user presence test" (e.g. by touching the token), you will receive a response, which is a JSON object (see spec for more details)

一旦用户执行“用户状态测试”(例如,通过触摸令牌),您将收到一个响应,这是一个JSON对象(详细信息请参阅spec)

dictionary RegisterResponse {
    DOMString registrationData;
    DOMString clientData;
};

This data contains several elements that your application needs to work with.

此数据包含应用程序需要处理的几个元素。

如何使用FIDO U2F允许用户对我的网站进行身份验证?

  1. The public key of the generated key pair -- You need to store this for future authentication use.
  2. 生成的密钥对的公钥——您需要将它存储起来以供将来的身份验证使用。
  3. The key handle of the generated key pair -- You also need to store this for future use.
  4. 生成的密钥对的密钥句柄——您还需要存储它以备将来使用。
  5. The certificate -- You need to check whether you trust this certificate and the CA.
  6. 证书——您需要检查您是否信任这个证书和CA。
  7. The signature -- You need to check whether the signature is valid (i.e. confirms to the key stored with the certificate) and whether the data signed is the data expected.
  8. 签名——您需要检查签名是否有效(例如,向存储在证书中的密钥进行确认),以及所签署的数据是否为预期的数据。

I have prepared a rough implementation draft for the relying party server in Java that shows how to extract and validate this information lately.

我为Java中的依赖方服务器准备了一个粗略的实现草案,展示了如何提取和验证这些信息。


Once the registration is complete and you have somehow stored the details of the generated key, you can sign requests.

一旦注册完成,并且您以某种方式存储了生成的密钥的细节,您就可以对请求进行签名。

As you said, this can be initiated short and sweet through the high-level JavaScript API:

如您所言,这可以通过高级JavaScript API进行快速而甜蜜的启动:

window.u2f.sign([{
    version : "U2F_V2",
    challenge : "c3RpbGwgYm9yZWQ/IQ",
    app_id : "http://example.org",
    sessionId : "42",
    keyHandle: "ZHVtbXlfa2V5X2hhbmRsZQ"
}], function (data) {

});

Here, you need to provide the key handle, you have obtained during registration. Once again, after the user performs a "user presence test" (e.g. by touching the token), you will receive a response, which is a JSON object (again, see spec for more details)

在这里,您需要提供密钥句柄,您在注册时已经获得。再一次,在用户执行“用户存在测试”(例如通过触摸令牌)之后,您将收到一个响应,它是一个JSON对象(同样,更多细节请参见spec)

dictionary SignResponse {
    DOMString keyHandle;
    DOMString signatureData;
    DOMString clientData;
};

You the need to validate the signature data contained herein.

您需要验证本文所包含的签名数据。

如何使用FIDO U2F允许用户对我的网站进行身份验证?

  1. You need to make sure that the signature matches the public key you have obtained before.
  2. 您需要确保签名与您以前获得的公钥匹配。
  3. You also need to validate that the string signed is appropriate.
  4. 您还需要验证签名的字符串是否合适。

Once you have performed these validations, you can consider the user authenticated. A brief example implementation of the server side code for that is also contained in my server example.

一旦执行了这些验证,就可以考虑已验证的用户。服务器端代码的一个简单示例实现也包含在我的服务器示例中。

#2


15  

I have recently written instructions for this, as well as listing all U2F server libraries (most of them bundles a fully working demo server), at developers.yubico.com/U2F. The goal is to enable developers to implement/integrate U2F without having to read the specifications.

我最近为它编写了一些说明,并在developers.yubico.com/U2F上列出了所有U2F服务器库(其中大多数都打包了一个完整的演示服务器)。目标是使开发人员能够实现/集成U2F,而不必阅读规范。

Disclaimer: I work as a developer at Yubico.

免责声明:我是Yubico的一名开发人员。