@sanity/webhook
Version:
Toolkit for dealing with GROQ-powered webhooks delivered by Sanity.io
208 lines (191 loc) • 6.2 kB
TypeScript
import type {RequestHandler} from 'express'
/**
* Asserts that the given request is valid.
* Throws an error if the request is invalid.
*
* @param request - The Connect/Express-like request to verify
* @param secret - The secret to use for verifying the signature
* @public
*/
export declare function assertValidRequest(
request: ConnectLikeRequest,
secret: string,
): Promise<void>
/**
* Asserts that the given signature is valid.
* Throws an error if the signature is invalid.
*
* @param stringifiedPayload - The stringified payload to verify - should be straight from the request, not a re-encoded JSON string, as this in certain cases will yield mismatches due to inconsistent encoding.
* @param signature - The signature to verify against
* @param secret - The secret to use for verifying the signature
* @public
*/
export declare function assertValidSignature(
stringifiedPayload: string,
signature: string,
secret: string,
): Promise<void>
/**
* A Connect/Express-like request object, containing a `headers` object and a `body` property.
*
* @public
*/
export declare interface ConnectLikeRequest<B = unknown> {
headers: Record<string, string | string[] | undefined>
body: B
}
/**
* A decoded signature header
*
* @public
*/
export declare interface DecodedSignature {
/**
* The timestamp the signature was created
*/
timestamp: number
/**
* The hashed payload (base64url encoded)
*/
hashedPayload: string
}
/**
* Decode a signature header into a timestamp and hashed payload.
*
* @param signaturePayload - The signature header to decode
* @returns An object with the decoded timestamp and hashed payload
* @public
*/
export declare function decodeSignatureHeader(signaturePayload: string): DecodedSignature
/**
* Encodes a signature header for the given payload and timestamp.
*
* @param stringifiedPayload - The stringified payload to verify - should be straight from the request, not a re-encoded JSON string, as this in certain cases will yield mismatches due to inconsistent encoding.
* @param timestamp - The timestamp to use for the signature
* @param secret - The secret to use for verifying the signature
* @returns A promise that resolves to the encoded signature header
* @public
*/
export declare function encodeSignatureHeader(
stringifiedPayload: string,
timestamp: number,
secret: string,
): Promise<string>
/**
* Checks whether or not the given error is a signature error.
*
* @param error - The error to check.
* @returns `true` if the error is a signature error, otherwise `false`.
* @public
*/
export declare function isSignatureError(error: unknown): error is WebhookSignatureError
/**
* Checks if the given request is valid.
*
* @param request - The Connect/Express-like request to verify
* @param secret - The secret to use for verifying the signature
* @returns Promise that resolves to `true` if the request is valid, `false` otherwise.
* @public
*/
export declare function isValidRequest(
request: ConnectLikeRequest,
secret: string,
): Promise<boolean>
/**
* Checks if the given signature is valid.
*
* @param stringifiedPayload - The stringified payload to verify - should be straight from the request, not a re-encoded JSON string, as this in certain cases will yield mismatches due to inconsistent encoding.
* @param signature - The signature to verify against
* @param secret - The secret to use for verifying the signature
* @returns A promise that resolves to `true` if the signature is valid, `false` otherwise.
* @public
*/
export declare function isValidSignature(
stringifiedPayload: string,
signature: string,
secret: string,
): Promise<boolean>
/**
* Express/Connect style middleware that verifies the signature of a request.
* Should be added _after_ a body parser that parses the request body to _text_, not parsed JSON.
*
* @example
* ```ts
* import express from 'express'
* import bodyParser from 'body-parser'
* import {requireSignedRequest} from '@sanity/webhook'
*
* express()
* .use(bodyParser.text({type: 'application/json'}))
* .post(
* '/hook',
* requireSignedRequest({secret: process.env.MY_WEBHOOK_SECRET, parseBody: true}),
* function myRequestHandler(req, res) {
* // Note that `req.body` is now a parsed version, set `parseBody` to `false`
* // if you want the raw text version of the request body
* },
* )
* .listen(1337)
* ```
*
* @param options - Options for the middleware
* @returns A middleware function
* @public
*/
export declare function requireSignedRequest(options: SignatureMiddlewareOptions): RequestHandler
/**
* The name of the header that contains the signature.
*
* @public
*/
export declare const SIGNATURE_HEADER_NAME = 'sanity-webhook-signature'
/**
* Options for the `requireSignedRequest` middleware
*
* @public
*/
export declare interface SignatureMiddlewareOptions {
/**
* The secret to use for verifying the signature
*/
secret: string
/**
* Whether or not to parse the request body as JSON on success (assigns it to `request.body`).
* Default: `true`
*/
parseBody?: boolean
/**
* Whether or not to respond with an error when the signature is invalid.
* If `false`, it will call the `next` function with the error instead.
* Default: `true`
*/
respondOnError?: boolean
}
/**
* Error types used on signature errors.
* Includes `type` and `statusCode` properties.
*
* @public
*/
export declare type WebhookSignatureError = WebhookSignatureValueError | WebhookSignatureFormatError
/**
* Error thrown when the signature format is invalid.
* This can happen when the signature is not a string or is not in the format of `t=<timestamp>,v=<signature>`.
* This error is also thrown when the timestamp is not a number or is not within the tolerance time.
*
* @public
*/
export declare class WebhookSignatureFormatError extends Error {
type: string
statusCode: number
}
/**
* Error thrown when the signature value does not match the expected value.
*
* @public
*/
export declare class WebhookSignatureValueError extends Error {
type: string
statusCode: number
}
export {}