Skip to content
DRvanR edited this page May 18, 2017 · 1 revision

U2F (Universal 2nd Factor)

Introductory reading

Anticipated challenges

During the U2F kick-off meeting, a number of challenges were anticipated. They are outlined below.

Need for a common origin

Unlike the SMS and Yubikey second factors, and very much like Tiqr, U2F needs a common origin (protocol, hostname and port) between registration (Self-Service, Registration Authority) and authentication (Gateway). In simple words: the U2F interaction must take place from one domain. One solution was thought to be to implement a second generic SAML second factor IdP on the Gateway or as a separate application.

Linux support

As of August 2015, Linux (Ubuntu 14.04) does not support U2F out of the box and requires changes to udev rules. This issue has been noted, but won't be addressed, since U2F is not yet widely used, not yet used in production and may be addressed by Linux or Google Chrome in the future.

Functional design

Like all other current second factors (SMS, Yubikey, Tiqr), U2F requires registration through the Self-Service and Registration Authority applications, after which it can be used on the Gateway to increase authentication security. Regarding user interaction, U2F's is the same as Yubikey's, but without an OTP entry field and more browser instructions.

Registration

In the Self-Service application, after the user has selected U2F as the second factor to register, the user is shown a page that will instruct him or her about the steps to take to register the U2F device with the Sterke Authenticatie infrastructure. These steps may include one or more of the following:

  • Make sure the U2F device is inserted in the computer
  • If the browser prompts the user to allow Sterke Authenticatie to register the U2F device, confirm
  • Press the button on the U2F device, which will blink

Error conditions:

  • The user aborts the registration of the device. This is our UI or the browser back button.
  • The user denies registration of the device through the browser UI.
  • Chrome Runtime response message error codes returned through U2F JS API wrapper library, see 3.1.2 and 4.3 of the FIDO U2F Javascript API document.

For the time being, we assume all U2F devices to be USB devices with a blinking button.

Authentication (signing)

Usage of a U2F second factor happens through an assertion signing process. During vetting in the Registration Authority application, or during authentication in the Gateway, the user is shown a page that will instruct him or her about the steps to take to sign the assertion.

  • Make sure the U2F device is inserted in the computer
  • Press the button on the U2F device

Error conditions:

  • The user aborts the signing. This is our UI or the browser back button.
  • Chrome Runtime response message error codes returned through U2F JS API wrapper library, see 3.1.2 and 4.3 of the FIDO U2F Javascript API document.

Technical design

Addressing the common origin challenge

U2F knows a concept called Application Facets. This concept allows for multiple web origins and native applications (facets) to make up a single logical application. The Gateway will serve a resource from its AppID URL (eg. https://sa-gw.surfconext.nl/u2f/app-id), which will state which AppIDs are facets of the logical application that is Sterke Authenticatie. When registering at the Self-Service, it will state that the https://sa-gw.surfconext.nl/u2f/app-id is its AppID, which will allow the Self-Service to register the connected U2F device in the logical application that is Sterke Authenticatie. Subsequently, in the Registration Authority and Gateway applications, a signing request can be performed using that same U2F device.

The Sterke Authenticatie AppID must be determined very carefully. If this ID is ever changed, identities can no longer authenticate using their U2F devices and must reregister their U2F devices.

SURFnet must make sure a file is served from the AppID URL. This can be performed during deploy and be served by nginx.

An example AppID resource:

{
    "trustedFacets": [{
        "version": {"major": 1, "minor": 0},
        "ids": [
            "https://ss.surfconext.nl",
            "https://ra.surfconext.nl",
            "https://gw.surfconext.nl"
        ]
    }]
}

U2F device interaction

The interaction with the device will be performed using a form and Yubikey's high-level wrapper around the low-level U2F JavaScript API.

Server validation

The U2F key handle will be the second factor's identifier, its public key will be stored in its attributes. These attributes will be stored in a JSON column in the second factor table. Server validation will be performed using Yubico's PHP U2F server library, which contains a validation class, unless it will prove unwieldy or exceptions cannot be handled properly, in which case we will refactor it to our needs.

Sign counter verification

To enable proper verification of U2F registrations and authentications, a counter state must be kept across the Self-Service, Registration Authority and Gateway applications. The Gateway is an application that may not have dependencies on other applications. Therefore it must implement the U2F verification server functionality. This functionality is exposed internally through a Symfony2 service. To prevent duplication, enable statistics about U2F usage across all user-facing applications and allow storage in a single location, that same service is exposed over an HTTP API.

API

The following API will be available:

  • register(RegistrationRequest, RegistrationResponse): RegistrationVerification[status: int]
  • verifyAuthentication(SignRequest, SignResponse): AuthenticationVerification[status: int]
  • revokeRegistration($keyHandle): RegistrationRevocation[status: int]

Which translates to an HTTP API as described API Design.

Request generation

Request generation and invalidation (eg. after a given time) are client concerns and must still be performed on the client.

Device registration storage

Because this is a concern that is separate from the Gateway's main functionality, namely operating as a step-up SAML proxy, the U2F state should be stored in a separate database, called u2f. This separate database stores key handles, public keys and signing counters from U2F devices. The additional database affects the deployment Ansible scripts and our development VM, however the impact is minimal.

Sign counter verification

Sign counter wrapping is not supported (eg. MAX_INT to 1). Should a counter wrap, a registrant must revoke, and register and vet his or her device again.

The sign counter does not necessarily increment monotonically; the U2F device may use a global counter, or authentications may get lost between client and server. Thus, sign counter verification succeeds if the authentication's sign counter is merely higher than the stored sign counter.

Conclusion

All in all, the centralised verification server reduces duplication and isolates complexity. This in turn eases development and maintenance, and simplifies implementation in the Self-Service and Registration Authority applications.

Prevent roll-out to production

The U2F second factor should not be rolled out to production. An enabled-by-default feature toggle will be available in the configuration of the Self-Service application that disables U2F in views and controllers.

Symfony2 Bundle

To allow reuse of U2F forms, resources and device verification, a Symfony2 Bundle will be created that encapsulates the logic and resources.

Attestation of device manufacture

If there is time, a directory containing trusted attestation certificate roots may be configured and used to verify a device has been manufactured by an owner of one of these certificates. This is a nice-to-have.

The certificates are provisioned during deploy.

Reading material: