//THE ACADEMY IS GROWING DAILY. CHECK OUT THE FIELD NOTES FROM TECHS HERE AT THE ACADEMY
>_DAEMONCORE // ACADEMY
← FIELD NOTES

WebAuthn and FIDO2 authentication flow: Understanding passkeys

2026.10.17//10 MIN READauthenticationweb-securitysecurity-architecturemethodology

// Understanding WebAuthn and FIDO2

WebAuthn is a game changer in the realm of authentication, enabling passwordless sign-ins through public key cryptography. It’s built on the FIDO2 standard, which incorporates the concept of passkeys. This method provides a pathway to secure authentication that sidesteps traditional password vulnerabilities. While it may sound simple on the surface, the underlying mechanics involve multiple moving parts: registration, authentication, attestation, and signature verification.

// Key Concepts

Passkeys

Passkeys are derived from public key cryptography. When a user registers a new authentication method with a WebAuthn-enabled application, a key pair is generated. The public key is stored on the server, while the private key remains secure on the user's device.

Attestation

Attestation serves as a mechanism for ensuring the authenticity of the hardware used to generate the keys. This process involves the client providing cryptographic proof that the keys were generated by a genuine device, which can be crucial in environments requiring heightened security measures.

Signature Verification

During authentication, the server sends a challenge to the client. The client uses the private key to sign this challenge, which the server then verifies using the stored public key. This flow eliminates the need for a password, reducing the attack surface significantly.

// Setting Up a WebAuthn Server

To implement WebAuthn, you can use a simple Node.js application. Below are steps to set up a WebAuthn server using Express and the @simplewebauthn/server library.

Step 1: Initial Setup

Install Node.js and create a new project:

mkdir webauthn-server
cd webauthn-server
npm init -y
npm install express @simplewebauthn/server cors body-parser

Step 2: Create the Server

Create a file named server.js and add the following code:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { generateRegistrationOptions, verifyRegistrationResponse, generateAuthenticationOptions, verifyAuthenticationResponse } = require('@simplewebauthn/server');

const app = express();
app.use(cors());
app.use(bodyParser.json());

let userDatabase = {}; // In-memory database for demonstration

app.post('/register', (req, res) => {
    const { username } = req.body;
    const options = generateRegistrationOptions({
        rpName: 'Example Corp',
        rpID: 'localhost',
        userID: username,
        userName: username,
        attestationType: 'none',
        excludeCredentials: []
    });
    userDatabase[username] = { options };
    res.json(options);
});

app.post('/verify-registration', (req, res) => {
    const { username, response } = req.body;
    const { options } = userDatabase[username];
    const verification = verifyRegistrationResponse({
        response,
        expectedChallenge: options.challenge,
        expectedOrigin: 'http://localhost',
        expectedRPID: 'localhost'
    });
    if (verification.verified) {
        userDatabase[username].credential = verification.registrationInfo;
        res.json({ verified: true });
    } else {
        res.json({ verified: false });
    }
});

app.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
});

Step 3: Running the Server

Start the server using the following command:

node server.js

You should see a message indicating the server is running. You can now send requests to your register and verify-registration endpoints.

// Example Registration Flow

Step 4: Register a User

1. Send a POST request to the /register endpoint:

   curl -X POST http://localhost:3000/register -H 'Content-Type: application/json' -d '{"username":"testuser"}'

2. Capture the response. You should receive a registration options JSON object with a challenge.

3. Use the WebAuthn API in the frontend to initiate the registration with these options. Capture the generated credential and send it to /verify-registration for verification.

Step 5: Verify Registration

1. Send the generated response to the server:

   curl -X POST http://localhost:3000/verify-registration -H 'Content-Type: application/json' -d '{"username":"testuser", "response":{...}}'

2. The server will verify the response and return whether the registration was successful.

// Authentication Flow

Step 6: Implementing Authentication

Add the following code to the server:

app.post('/authenticate', (req, res) => {
    const { username } = req.body;
    const options = generateAuthenticationOptions({
        allowCredentials: [userDatabase[username].credential],
        challenge: randomChallenge()
    });
    res.json(options);
});

app.post('/verify-authentication', (req, res) => {
    const { username, response } = req.body;
    const verification = verifyAuthenticationResponse({
        response,
        expectedChallenge: response.challenge,
        expectedOrigin: 'http://localhost',
        expectedRPID: 'localhost',
        authenticator: userDatabase[username].credential
    });
    res.json({ verified: verification.verified });
});

Step 7: Authentication Request

1. Send a POST request to the /authenticate endpoint:

   curl -X POST http://localhost:3000/authenticate -H 'Content-Type: application/json' -d '{"username":"testuser"}'

2. Capture the authentication options and use the WebAuthn API to authenticate.

3. Send the authentication response to /verify-authentication:

   curl -X POST http://localhost:3000/verify-authentication -H 'Content-Type: application/json' -d '{"username":"testuser", "response":{...}}'

// Defensive Implications

Utilizing WebAuthn can significantly reduce the risk of account compromise due to phishing or credential stuffing attacks. However, be mindful of:

  • Attestation: Ensure that proper attestation is configured to verify the legitimacy of devices.
  • Challenge Management: Use strong, unpredictable challenges to mitigate replay attacks.
  • Cross-Origin Risks: Be careful with your expectedOrigin to avoid cross-origin vulnerabilities.

// Checklist for WebAuthn Implementation

  • [ ] Implement user registration with proper handling of options.
  • [ ] Ensure verification of registration responses with attestation checks.
  • [ ] Implement authentication flows using secure challenges.
  • [ ] Regularly audit stored credentials and user data.
  • [ ] Keep up with WebAuthn specifications and best practices.

Implementing a WebAuthn and FIDO2 flow can be a significant enhancement to your authentication strategy. The approach reduces reliance on passwords and leverages the strength of public key cryptography.

--- // FIELDOPS REPORT AUTHORIZED BY: Bruce H. //