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.
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.
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).
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 is a variant of Base64 encoding that's URL and filename safe:
+, /, and = for padding-, _, and no paddingWebAuthn specifications use Base64URL encoding for JSON serialization because:
// 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 charsThese functions are optimized for typical WebAuthn data sizes:
For large data sets, consider streaming approaches, but WebAuthn data rarely exceeds a few KB per operation.
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.