Security

Implementing Passwordless Authentication with WebAuthn and Node.js

A guide to building a simple, secure, and passwordless authentication system using WebAuthn and Node.js.

December 20, 2023
3 min read
Implementing Passwordless Authentication with WebAuthn and Node.js

Introduction

Passwords are a thing of the past. They are insecure, hard to remember, and a pain to manage. Fortunately, there’s a better way: passwordless authentication with WebAuthn. In this article, I’ll show you how to build a simple, secure, and passwordless authentication system using WebAuthn and Node.js.

What is WebAuthn?

WebAuthn is a web standard for secure authentication that uses public-key cryptography to protect users from phishing attacks. Instead of a password, users can authenticate with a fingerprint, a security key, or other authenticators.

The Tech Stack: Node.js and Express

For this project, I used the following technologies:

  • Node.js: A popular and powerful JavaScript runtime.
  • Express: A minimal and flexible Node.js web application framework.

Architecture and Implementation

The core of the WebAuthn authentication system is a server that can:

  • Register a user’s public key.
  • Verify a user’s signature against their public key.
sequenceDiagram
    participant User
    participant Browser
    participant Server
    participant Authenticator
    
    Note over User,Authenticator: Registration Flow
    User->>Browser: Click "Register"
    Browser->>Server: Request challenge
    Server-->>Browser: Challenge + User ID
    Browser->>Authenticator: Create credential
    Authenticator->>User: Prompt (fingerprint/PIN)
    User-->>Authenticator: Authenticate
    Authenticator-->>Browser: Public key + Signature
    Browser->>Server: POST /register
    Server->>Server: Store public key
    Server-->>Browser: Success
    
    Note over User,Authenticator: Authentication Flow
    User->>Browser: Click "Login"
    Browser->>Server: Request challenge
    Server-->>Browser: Challenge
    Browser->>Authenticator: Sign challenge
    Authenticator->>User: Prompt (fingerprint/PIN)
    User-->>Authenticator: Authenticate
    Authenticator-->>Browser: Signature
    Browser->>Server: POST /authenticate
    Server->>Server: Verify with public key
    Server-->>Browser: Authentication successful

Server Implementation

The server is a simple Express application with two endpoints: /register and /authenticate.

The /register Endpoint

The /register endpoint is responsible for storing the user’s public key. When a user registers, they send their user ID and public key to the server. The server then stores the public key in a database (in this example, we’re using an in-memory object for simplicity).

app.post('/register', (req, res) => {
  const { userId, publicKey } = req.body;

  const publicKeyPem = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`;
  userPublicKeys[userId] = publicKeyPem;
  res.send('Registration successful');
});

The /authenticate Endpoint

The /authenticate endpoint is responsible for verifying a user’s signature. When a user wants to authenticate, they sign a piece of data with their private key and send the signature to the server. The server then uses the user’s public key to verify the signature.

app.post('/authenticate', (request, response) => {
  const { userId, signature, originalData } = request.body;
  const publicKey = userPublicKeys[userId];

  const originalDataBuffer = Buffer.from(originalData, 'base64');
  const verifier = crypto.createVerify('SHA256');
  verifier.update(originalDataBuffer);

  const signatureBuffer = Buffer.from(signature, 'base64');
  const isValid = verifier.verify(
    {
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      saltLength: 32,
    },
    signatureBuffer
  );

  if (isValid) {
    response.send('Authentication successful');
  } else {
    response.status(401).send('Authentication failed');
  }
});

Conclusion

WebAuthn is a powerful and secure alternative to passwords. By using WebAuthn, you can provide your users with a seamless and secure authentication experience. This project demonstrates how easy it is to implement a simple WebAuthn server using Node.js and Express.

Tags

#WebAuthn #Node.js #Express #Authentication #Security
Rommel

Written by Rommel Saquicela

Senior Tech Lead & Solutions Architect

View Profile