Ditch the Passwords!

Joris Verbogt
Joris Verbogt
Dec 16 2022
Posted in Engineering & Technology

Web Authentication is here

Ditch the Passwords!

Nowadays, most online services use some form of 2-factor authentication when logging in, and over the last couple of years, users got used to having SMS codes sent to their phone or using an authenticator app.

The problem with Passwords and 2FA

The main reason for the advent of 2FA was that 4 out of 5 computer system hacks are caused by password guessing and this gets easier by the day, no matter how strong your password seems.

A second factor one-time password mitigates this problem by requiring the hacker to also be able to produce the one-time password.

The problem is that most services and users rely on SMS messages to retrieve their 6-digit code to finish their login. SMS is relatively easy to intercept because it is sent over an inherently insecure channel.

One-time password apps on mobile devices are harder to break as it would require access to the physical device. Hardware tokens such as Yubikeys or other U2F mechanisms are even better but also have their downsides, as they require the purchase of such devices that can be lost or forgotten.

What is WebAuthn

The WebAuthn (short for Web Authentication) standard aims to overcome these inherent flaws in other login methods by employing the latest technology, both in software and in device hardware.

The idea is that since online services run inside a browser and that browser runs on hardware with built-in security features, it is possible to combine these two and provide an easy, secure and trusted authentication experience.

WebAuthn:

  • uses Public Key Encryption to ensure secure transmission of information. Private keys are kept on the (hardware) authenticator device so don't require a shared secret between the origin and the authenticator like (one-time) passwords do.
  • uses hardware-provided biometrics. The user's device can employ whatever means are available and applicable, like fingerprint, facial recognition, iris scan or a combination of measures.
  • links credentials to origin, just like browser cookies. This means a credential for one origin will never be used to attempt login in another service that tries to impersonate the actual one.
  • allows for specific attestation of the authenticator, so the origin can verify the authenticity of the login credentials, especially useful for internal and enterprise use.

For more information, and to see these mechanisms in action, please take a look at this excellent demo website for WebAuthn.

Implementing WebAuthn

The WebAuthn standard is limited to the protocols and data structures between the user and the origin server, it does not make any assumptions or poses any limits on how accounts are created or how the user identifies themselves as whom they say they are.

To give an example of what a typical exchange will look like, let's first describe the various steps taken:

Phase 1: Create a WebAuthn credential

First, we need to set up a credential that we can use to authenticate against the service we want to use.

Step 1: Origin server sends a challenge

Basically this is just a sufficiently long string of random characters

const challenge = Uint8Array.from(randomStringFromServer, c => c.charCodeAt(0))

Step 2: Client app creates a credential

Depending on the use case, the client app sets the parameters for the browser to ask the user for permission to create a credential for the online service:

const credentialCreationRequest = {
  challenge: challenge,
  rp: {
    name: "Notificare Dashboard",
    id: "dashboard.notifica.re",
  },
  user: {
    id: Uint8Array.from(credentialId, c => c.charCodeAt(0)),
    name: "user@example.com",
    displayName: "Example User",
  },
  pubKeyCredParams: [{alg: -7, type: "public-key"}],
  authenticatorSelection: {
    authenticatorAttachment: "cross-platform",
  },
  timeout: 60000,
  attestation: "direct"
}

A couple of noteworthy parameters in this request:

  • rp: the requesting party, in this example the Notificare Dashboard
  • authenticatorSelection: which type of authenticator to use to create the credentials. In this example it requires an external key, like a Yubikey. In a modern browser and device this could be the device itself (e.g. Touch ID on your MacBook)
  • attestation: how to attest this authenticator. In this case the authenticator itself is used, which may expose details about the user. It is also possible to anonymize or leave out any attestation.

Step 3: Generate a public/private keypair

The user's browser uses the authenticator (internal or external, e.g. a Yubikey) for this

const credential = await navigator.credentials.get({
    publicKey: credentialCreationRequest
});

Chrome will now ask to create a passkey:

Likewise, Safari will ask you to store a passkey:

Step 4: Client app sends resulting public credential to origin server

After this point, it is up to the origin server to verify and validate the credentials, which is beyond the scope of this blog post. Various libraries exist for most common server languages and frameworks.

Phase 2: Authenticating with WebAuthn

Assuming the credentials were found to be valid, the user's browser can now be used for any authentication to the origin server, without the need to ever share secrets or providing passwords or one-time codes.

Step 1: Origin server sends a challenge

Similar to the first step when creating the credential

const challenge = Uint8Array.from(randomStringFromServer, c => c.charCodeAt(0))

Step 2: Client app creates a signing request:

The authenticator will cryptographically sign the challenge:

const assertion = await navigator.credentials.get({
    publicKey: {
      challenge: challenge,
      allowCredentials: [{
        id: Uint8Array.from(credentialId, c => c.charCodeAt(0)),
        type: 'public-key',
        transports: ['usb', 'ble', 'nfc'],
      }],
      timeout: 60000,
    }
});

Again, as you can see, this request is configurable. It's possible to limit the type of authenticator devices, in this example it allows USB, Bluetooth and NFC devices.

Chrome will now prompt to authenticate this login session:

Step 3: Client app sends the signed data to the origin server

After this point, the origin server verifies the signature and authenticates the user.

Conclusion

As you can see, from the user's point of view this all looks very familiar, depending on the platform and browser they are comfortable with. It also doesn't involve setting up and using different hardware keys and keeping track of account names, everything is linked to the device they are using to access the service.

From a security point of view, this is as secure as the method used to log in to the authenticator device and will finally allow us to ditch those passwords!

As the example above shows, implementation is pretty straight forward from within the browser. We expect most online services to adopt the new standard in the coming years.

At Notificare, we are always looking for better solutions, and we are currently investigating how we can replace the sometimes cumbersome 2FA authenticator apps with the new WebAuthn standard if that is available in the user's device.

We will make sure this is thoroughly tested and migration can be done seamlessly for all users. Our aim is to launch this as a part of the next major release of the Dashboard.

As always, we hope you liked this article and if you have anything to add, we are available via our Support Channel.

Keep up-to-date with the latest news