or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdbrowser-support.mddata-encoding.mderror-handling.mdindex.mdregistration.mdserver.md
tile.json

data-encoding.mddocs/

Data Encoding Utilities

Utilities for converting between Base64URL strings and ArrayBuffers, essential for WebAuthn data handling. WebAuthn APIs use ArrayBuffers, but JSON serialization requires string encoding, making these conversion functions crucial for client-server communication.

Capabilities

Base64URL String to Buffer

Converts a Base64URL-encoded string to an ArrayBuffer for use with WebAuthn APIs.

/**
 * Convert from a Base64URL-encoded string to an Array Buffer. Best used when converting a
 * credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
 * excludeCredentials
 * 
 * Helper method to compliment `bufferToBase64URLString`
 * @param base64URLString The Base64URL-encoded string to convert
 * @returns ArrayBuffer containing the decoded binary data
 */
function base64URLStringToBuffer(base64URLString: string): ArrayBuffer;

Usage Examples:

import { base64URLStringToBuffer } from "@simplewebauthn/browser";

// Convert challenge from server JSON to ArrayBuffer for WebAuthn
const challengeString = "dGVzdC1jaGFsbGVuZ2U"; // From server JSON
const challengeBuffer = base64URLStringToBuffer(challengeString);

// Convert user ID from server JSON to ArrayBuffer
const userIdString = "dXNlci0xMjM0NTY"; // From server JSON  
const userIdBuffer = base64URLStringToBuffer(userIdString);

// Convert credential IDs for allowCredentials/excludeCredentials
const credentialIds = [
  "Y3JlZGVudGlhbC0xMjM0NTY",
  "YW5vdGhlci1jcmVkZW50aWFsLTc4OQ"
];

const allowCredentials = credentialIds.map(id => ({
  type: "public-key" as const,
  id: base64URLStringToBuffer(id),
  transports: ["usb", "nfc", "ble", "hybrid"] as const,
}));

console.log("Converted credential IDs:", allowCredentials);

This function handles the Base64URL to Base64 conversion (replacing - with + and _ with /), adds proper padding, and converts the decoded binary string to an ArrayBuffer via Uint8Array.

Buffer to Base64URL String

Converts an ArrayBuffer to a Base64URL-encoded string suitable for JSON serialization and server transmission.

/**
 * Convert the given array buffer into a Base64URL-encoded string. Ideal for converting various
 * credential response ArrayBuffers to string for sending back to the server as JSON.
 * 
 * Helper method to compliment `base64URLStringToBuffer`
 * @param buffer The ArrayBuffer to convert
 * @returns Base64URL-encoded string suitable for JSON transmission
 */
function bufferToBase64URLString(buffer: ArrayBuffer): string;

Usage Examples:

import { bufferToBase64URLString } from "@simplewebauthn/browser";

// Convert WebAuthn response data for server transmission
const credential = await navigator.credentials.create(options);

const registrationResponse = {
  id: credential.id,
  rawId: bufferToBase64URLString(credential.rawId),
  response: {
    clientDataJSON: bufferToBase64URLString(credential.response.clientDataJSON),
    attestationObject: bufferToBase64URLString(credential.response.attestationObject),
  },
  type: credential.type,
};

// Send to server as JSON
await fetch("/webauthn/register/finish", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(registrationResponse),
});

// Convert authentication response data
const authCredential = await navigator.credentials.get(authOptions);

const authResponse = {
  id: authCredential.id,
  rawId: bufferToBase64URLString(authCredential.rawId),
  response: {
    clientDataJSON: bufferToBase64URLString(authCredential.response.clientDataJSON),
    authenticatorData: bufferToBase64URLString(authCredential.response.authenticatorData),
    signature: bufferToBase64URLString(authCredential.response.signature),
    userHandle: authCredential.response.userHandle 
      ? bufferToBase64URLString(authCredential.response.userHandle)
      : undefined,
  },
};

console.log("Authentication response:", authResponse);

This function converts the ArrayBuffer to a Uint8Array, builds a binary string, encodes it with btoa(), and then converts from Base64 to Base64URL format (replacing + with -, / with _, and removing padding = characters).

Data Flow in WebAuthn

These utilities are essential for the WebAuthn data flow:

import { 
  base64URLStringToBuffer, 
  bufferToBase64URLString,
  startRegistration 
} from "@simplewebauthn/browser";

// 1. Server sends JSON with Base64URL-encoded data
const serverOptions = {
  challenge: "dGVzdC1jaGFsbGVuZ2U",
  user: {
    id: "dXNlci0xMjM0NTY",
    name: "testuser",
    displayName: "Test User"
  },
  // ... other options
};

// 2. Library converts to WebAuthn format internally
const webauthnOptions = {
  challenge: base64URLStringToBuffer(serverOptions.challenge),
  user: {
    ...serverOptions.user,
    id: base64URLStringToBuffer(serverOptions.user.id),
  },
  // ... other conversions
};

// 3. WebAuthn API returns ArrayBuffers
const credential = await navigator.credentials.create({ publicKey: webauthnOptions });

// 4. Library converts back to Base64URL for JSON transmission
const response = {
  id: credential.id,
  rawId: bufferToBase64URLString(credential.rawId),
  response: {
    clientDataJSON: bufferToBase64URLString(credential.response.clientDataJSON),
    attestationObject: bufferToBase64URLString(credential.response.attestationObject),
  },
};

// 5. Send JSON to server
await fetch("/webauthn/register/finish", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(response),
});

Base64URL vs Base64

Base64URL is a variant of Base64 encoding that's URL and filename safe:

  • Base64: Uses +, /, and = for padding
  • Base64URL: Uses -, _, and no padding

WebAuthn specifications use Base64URL encoding for JSON serialization because:

  1. URL-safe characters don't need escaping in URLs or form data
  2. No padding characters simplify string handling
  3. Compatible with JSON without special character escaping
// Example of the difference:
const buffer = new ArrayBuffer(16);
const view = new Uint8Array(buffer);
view.set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);

// Standard Base64 (hypothetical)
// "AQIDBAUGBwgJCgsMDQ4PEA=="

// Base64URL (actual result)
// "AQIDBAUGBwgJCgsMDQ4PEA"
const base64url = bufferToBase64URLString(buffer);
console.log("Base64URL:", base64url); // No padding, URL-safe chars

Performance Considerations

These functions are optimized for typical WebAuthn data sizes:

  • Challenges: Usually 32-64 bytes
  • User IDs: Usually 8-64 bytes
  • Credential IDs: Usually 16-255 bytes
  • Signatures: Usually 64-256 bytes
  • Public Keys: Usually 65-133 bytes

For large data sets, consider streaming approaches, but WebAuthn data rarely exceeds a few KB per operation.

Error Handling

Both functions are designed to be robust:

try {
  const buffer = base64URLStringToBuffer(invalidString);
} catch (error) {
  console.error("Invalid Base64URL string:", error);
}

try {
  const string = bufferToBase64URLString(buffer);
  console.log("Conversion successful:", string);
} catch (error) {
  console.error("Buffer conversion failed:", error);
}

The functions will throw standard JavaScript errors for invalid inputs like malformed Base64URL strings or invalid ArrayBuffers.