Since the inception of the internet, we have mostly ever gotten to use the mighty password-based authentication, from our banking applications, education, government agencies, etc,... It's a very logical thing to say the original designers of the password-based authorization system did not envision it to become the core authentication model for the worldwide network of computers, smartphones, and all sorts of interconnected devices that have become integral parts of our lives.

While the password-based authentication scheme has become ubiquitous over the internet, it has many flaws and limitations that we have sadly accepted to live with.

(1) Problems with password-based authentication

  • Prone to Phishing Attacks

Phishing attacks where users get tricked into providing their password and username credentials to fake websites are extremely effective and harmful in the current password-based authentication. It's estimated that hundreds of millions of dollars are lost every year due to phishing attacks.

  • Password/Credential Fatigue

Given the fact that almost every website or application over the internet requires a password-based authentication scheme, many users forget passwords, or even worse there's a tendency to re-use same passwords across many websites.

  • Lack Of Privacy

Many people over the internet tend to use personal information in their passwords and usernames, passwords get easily leaked or stolen almost every year due to bad security practices from some service providers/website operators and developers.

Given all the limitations of password-based authentication schemes, many industry giants like Google, Apple, and others have been working on common passwordless protocols & standards such as FIDO2 and WebAuthn.

These protocols have enabled the emergence of passkeys which enable users to authenticate over the internet with device-built authentication primitives like fingerprints, facial recognition (FaceID), patterns, etc,...

(2) Advantages of password-less authentication

  • Safe Against Phishing Attacks

Phishing attacks where users get tricked into supplying private authentication credentials are directly rendered useless given the fact that password-less authentication doesn't require easily stolen credentials.

  • Much More Convenient

It's much more convenient, the user doesn't need to remember a gazillion passwords, and it's as simple as inputting the fingerprint, face authentication, or pattern and letting the service authenticate.

  • Privacy-Preserving

Given the fact that password-less authentication uses public key cryptography, there's no more need to pass private information to the service provider's backend to get authenticated, only the public key is passed to the server, and private keys remain on the device.

(3) Implementing password-less authentication

  • Step 1: Since Passkeys are implemented on top of the Webauthn protocol, the creation of the passkeys on the client simply uses Webauthn for passkeys creation and initiation.
// First create the public key configuration object.

 const publicKeyCredentialCreationOptions = {
    challenge: new Uint8Array([117, 61, 252, 231, 191, 241]),
    rp: {
      name: "Example",
      // A common error happens if the origin doesn't match rp.id value
      id: "localhost",
    },
    user: {
      id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
      name: "jack2000",
      displayName: "Jack Jill",
    },
    pubKeyCredParams: [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}],
    authenticatorSelection: {
      authenticatorAttachment: "platform",
      requireResidentKey: true,
    }
  };


// Then initiate the creation, and a popup will come on the screen
await navigator.credentials.create(publicKey:publicKeyCredentialCreationOptions)
  • Step 2: After the user has input their fingerprint/face recognition/etc, the promise will get resolved and it will return the public key to the client frontend. The front end shall send the public key to the server and the server will use it later to validate signed messages.
  • Step 3: The backend will store the public key generated and the associated credential ID with associated user data.
  • Step 4: When the backend needs to authenticate the client, it will send a challenge/message to sign, the client will sign it and send the signed message to the backend, the backend can later use the the challenge and the signed message to validate if it was from the private associated to the public it currently stores.

And that's the full flow of implementing passkeys. I will soon be sharing full code snippets on my GitHub