Browse documentation

Documentation

Receive lifecycle webhooks

Verify signed connection lifecycle events and process retries idempotently.

Authlane delivers connection changes through a transactional outbox with exponential retry.

Prerequisites

Configure a tenant webhook URL and signing secret, preserve the raw request bytes, and keep a store of processed event IDs.

Implement the workflow

Verify the exact string <timestamp>.<raw-body> before parsing JSON:

TypeScript
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyAuthlaneWebhook(
  rawBody: string,
  timestamp: string,
  signature: string,
  secret: string,
): boolean {
  const expected = Buffer.from(
    createHmac('sha256', secret).update(timestamp + '.' + rawBody).digest('hex'),
    'hex',
  );
  const received = Buffer.from(signature, 'hex');
  return received.length === expected.length && timingSafeEqual(received, expected);
}

Read X-Authlane-Signature, X-Authlane-Timestamp, X-Authlane-Event, and Idempotency-Key. Reject timestamps outside a short tolerance such as five minutes, reserve the idempotency key before side effects, and return 2xx quickly.

Events are connection.connected, connection.disconnected, connection.expired, connection.refreshed, and connection.error. Each payload includes externalUserId, serviceId, and connectionId inside data.

Expected result

Retries with the same event ID do not repeat side effects, and only a valid current signature reaches business logic.

Handle errors

Return non-2xx only when a retry can help. Monitor delivery backlog and clock drift; never log the signing secret or raw sensitive payload extensions.

Security boundary

Verify raw bytes and timestamp before parsing. Rotate the webhook secret through tenant settings and retain the previous value only for the intended overlap.

Next step

Use connection lifecycle to map events to UI state.