Skip to content
LogoLogo

Crypto and auth

These packages call crypto.subtle for every hash, signature, key derivation, and cipher. The same code signs and verifies in a browser, a Worker, and Node.

  • web-crypto wraps digest, hmac, and hkdf as bytes-in, bytes-out functions, and builds Ed25519 and X25519 keys from 32-byte seeds.
  • password hashes and verifies passwords with PBKDF2.
  • webhooks verifies and signs webhooks from Stripe, GitHub, Slack, and Standard Webhooks senders.
  • oauth1 signs OAuth 1.0a requests.
  • web-push sends encrypted Web Push notifications with VAPID.
  • dkim signs and verifies email.

Verify a webhook and rate limit the sender

import * as RateLimit from '@portable/rate-limit';
import * as Webhooks from '@portable/webhooks';
 
const limiter = RateLimit.create({ limit: 100, period: 60_000 });
 
export default {
  async fetch(request: Request, env: { GITHUB_SECRET: string }) {
    const result = await limiter.take(
      request.headers.get('cf-connecting-ip') ?? 'unknown',
    );
    if (!result.allowed) {
      return new Response(null, {
        status: 429,
        headers: RateLimit.headers(result),
      });
    }
    try {
      const { body } = await Webhooks.verify(request, {
        scheme: Webhooks.github,
        secret: env.GITHUB_SECRET,
      });
      await handle(JSON.parse(body));
      return new Response(null, { status: 204 });
    } catch (error) {
      if (error instanceof Webhooks.VerificationError) {
        return new Response(null, { status: 401 });
      }
      throw error;
    }
  },
};