Next.js Discord

Discord Forum

Webhook

Unanswered
Erythrina gall wasp posted this in #help-forum
Open in Discord
Erythrina gall waspOP
How i can protect my webhook?

3 Replies

Erythrina gall waspOP
import {HTTP_STATUS_CODE} from '@/lib/consts/http-status-code';

import {BodyParseError, getModelUrlPath, parseBody} from './_tools/parse-body';
import {parseSignature, SignatureError} from './_tools/parse-signature';
import {revalidatePage} from './_tools/revalidate-page';

export async function POST(request: Request) {
  try {
    parseSignature(request);
    const {previousValue, newValue} = await parseBody(request);

    revalidatePage({
      prevUrlPath: getModelUrlPath(previousValue),
      newUrlPath: getModelUrlPath(newValue),
    });

    return new Response(null, {status: HTTP_STATUS_CODE.OK});
  } catch (error) {
    let response: Response;

    if (error instanceof SignatureError) {
      response = new Response(null, {status: HTTP_STATUS_CODE.UNAUTHORIZED});
    } else if (error instanceof BodyParseError) {
      response = new Response(null, {status: HTTP_STATUS_CODE.BAD_REQUEST});
    } else {
      response = new Response(null, {status: HTTP_STATUS_CODE.SERVER_ERROR});
    }
    return response;
  }
}
import jwt from 'jsonwebtoken';

import {env} from '@/env';

export class SignatureError extends Error {
  constructor() {
    super();
    this.name = SignatureError.name;
  }
}

export async function parseSignature(request: Request) {
  const authorization = request.headers.get('Authorization');
  if (!authorization) {
    throw new SignatureError();
  }

  try {
    jwt.verify(extractSignature(authorization), env.WEBHOOK_SIGNING_KEY);
  } catch {
    throw new SignatureError();
  }
}

// https://datatracker.ietf.org/doc/html/rfc6750
const AUTH_TYPE = 'Bearer';

function extractSignature(authorization: string) {
  const [type, signature] = authorization.split(' ');

  if (type !== AUTH_TYPE) {
    throw new SignatureError();
  }
  return signature;
}
Is it a good way to protect my webhook?