Given the provided OpenAPI specifications, here is an updated version of the quickstart guide that includes API details based on Contribyard’s documented endpoints:


Integrating Passkey Authentication with Contribyard in Next.js (Example)

Prerequisites

Before starting, ensure you have:

  1. A Next.js application.
  2. Installed the @github/webauthn-json package.
  3. Access to the Contribyard API.

Step 1: Install Required Dependencies

In your Next.js project, install the necessary npm package:

npm install @github/webauthn-json

Step 2: Configure Contribyard API

Set up your environment variables for Contribyard API access by adding the following to your .env.local file:

NEXT_PUBLIC_CONTRIBYARD_API_KEY=your_contribyard_api_key

Replace your_contribyard_api_key with your actual API key from Contribyard.

Step 3: Implement Registration Flow

Create a register.js page in your Next.js pages directory for the user registration flow.

import { startRegistration } from "@github/webauthn-json";

export default function Register() {
  const handleRegister = async () => {
    try {
      const response = await fetch("/api/register-challenge", {
        method: "POST",
      });

      const challengeData = await response.json();

      const credentials = await startRegistration(challengeData);

      const result = await fetch("/api/register", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(credentials),
      });

      if (result.ok) {
        alert("Registration successful!");
      } else {
        alert("Registration failed!");
      }
    } catch (error) {
      console.error("Error during registration:", error);
    }
  };

  return (
    <div>
      <h1>Register with Passkey</h1>
      <button onClick={handleRegister}>Register</button>
    </div>
  );
}

Step 4: Create API Endpoints for the Registration Flow

Create two API routes in the pages/api/ directory to interact with Contribyard’s /v1/passkey_attestations and /v1/passkey_attestations/{id}/verify endpoints.

register-challenge.js

This endpoint retrieves the attestation options from Contribyard:

export default async function handler(req, res) {
  const response = await fetch("https://api.contribyard.com/v1/passkey_attestations", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NEXT_PUBLIC_CONTRIBYARD_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      attestation: {
        user_id: "new_user", // Customize this value as needed
      },
    }),
  });

  const attestationOptions = await response.json();
  res.status(201).json(attestationOptions.response.credential_creation_options);
}

register.js

This endpoint verifies the attestation:

export default async function handler(req, res) {
  const { id, rawId, response, type } = req.body;

  const responseBody = {
    attestation: {
      id,
      rawId,
      response,
      type,
    },
  };

  const verifyResponse = await fetch(`https://api.contribyard.com/v1/passkey_attestations/${id}/verify`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NEXT_PUBLIC_CONTRIBYARD_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(responseBody),
  });

  if (verifyResponse.ok) {
    res.status(201).json({ success: true });
  } else {
    res.status(500).json({ success: false });
  }
}

Step 5: Implement Authentication Flow

Now, let’s implement the authentication flow. Create a login.js page for user authentication.

import { startAuthentication } from "@github/webauthn-json";

export default function Login() {
  const handleLogin = async () => {
    try {
      const response = await fetch("/api/login-challenge", {
        method: "POST",
      });

      const challengeData = await response.json();

      const credentials = await startAuthentication(challengeData);

      const result = await fetch("/api/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(credentials),
      });

      if (result.ok) {
        alert("Login successful!");
      } else {
        alert("Login failed!");
      }
    } catch (error) {
      console.error("Error during login:", error);
    }
  };

  return (
    <div>
      <h1>Login with Passkey</h1>
      <button onClick={handleLogin}>Login</button>
    </div>
  );
}

Step 6: Create API Endpoints for the Authentication Flow

Create two API routes to handle authentication using the /v1/passkey_assertions and /v1/passkey_assertions/{id}/verify endpoints.

login-challenge.js

This endpoint retrieves the assertion challenge from Contribyard:

export default async function handler(req, res) {
  const response = await fetch("https://api.contribyard.com/v1/passkey_assertions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NEXT_PUBLIC_CONTRIBYARD_API_KEY}`,
      "Content-Type": "application/json",
    },
  });

  const assertionOptions = await response.json();
  res.status(201).json(assertionOptions.response.publicKey);
}

login.js

This endpoint verifies the assertion:

export default async function handler(req, res) {
  const { id, rawId, response, type } = req.body;

  const responseBody = {
    assertion: {
      id,
      rawId,
      response,
      type,
    },
  };

  const verifyResponse = await fetch(`https://api.contribyard.com/v1/passkey_assertions/${id}/verify`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.NEXT_PUBLIC_CONTRIBYARD_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(responseBody),
  });

  if (verifyResponse.ok) {
    res.status(200).json({ success: true });
  } else {
    res.status(500).json({ success: false });
  }
}

Conclusion

By following this guide, you have successfully integrated Passkey authentication using Contribyard’s API with Next.js. You can now extend this with better error handling, user feedback, and production-level security features. For further customization, refer to the Contribyard API documentation.