AWS SigV4 cover

AWS SigV4 in the Browser for Cloudflare R2

Last updated:

Cloudflare R2 speaks an S3-compatible API. In MV3 service workers, you can sign requests on-device using WebCrypto and send them directly to https://{account}.r2.cloudflarestorage.com. This post covers canonical requests, the string-to-sign, and HMAC signatures in the browser.

Canonical request

// utils/s3-fixed.js (excerpt)
const canonicalRequest = [
  method,
  path,
  query,
  canonicalHeaders + '\n',
  signedHeaders,
  payloadSha256,
].join('\n');

const hashedCanonicalRequest = hex(new Uint8Array(
  await crypto.subtle.digest('SHA-256', new TextEncoder().encode(canonicalRequest))
));

Derive signing key

// Date scope: YYYYMMDD/region/service/aws4_request
const kDate = await hmac('AWS4' + secretAccessKey, date);
const kRegion = await hmac(kDate, region);
const kService = await hmac(kRegion, service);
const kSigning = await hmac(kService, 'aws4_request');

String to sign and signature

const stringToSign = [
  'AWS4-HMAC-SHA256',
  amzDate,
  scope,
  hashedCanonicalRequest,
].join('\n');

const signature = hex(new Uint8Array(
  await crypto.subtle.sign('HMAC', await importKey(kSigning), encoder.encode(stringToSign))
));

Common pitfalls

See also: Presigned URLs for Fast and Safe R2 Downloads.

Try R2 Dashboard for free

Runs entirely in your browser. No sign-up required.