octokit/webhooks-methods.js

Deno support is undocumented

rojvv opened this issue · 4 comments

rojvv commented

How should we use this on Deno?

I've imported it without problems using the URL https://cdn.skypack.dev/@octokit/webhooks-methods?dts.

I'm using the verify method this way:

await verify(secret, payload, "X-Hub-Signature-256");

But it's returning false every time.

Here's my full code:

import { Application } from "https://deno.land/x/oak/mod.ts";
import { verify } from "https://cdn.skypack.dev/@octokit/webhooks-methods?dts";

const app = new Application();

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (_err) {
    ctx.response.status = 500;
  }
});

const secret = "...";

app.use(async (ctx) => {
  const signature = ctx.request.headers.get("X-Hub-Signature-256");
  if (signature) {
    const payload = await ctx.request.body({ type: "text" }).value;
    const result = await verify(secret, payload, signature);
    console.log(result);
  }
  ctx.response.status = 200;
});
rojvv commented

I accidentally clicked on 'bug'. The bug label might not be accurate.

I'm experiencing the same problem with both X-Hub-Signature and X-Hub-Signature-256.

Alright, here's a working example of GitHub signature verification for Deno:

import { Buffer } from "https://deno.land/std/io/mod.ts";
import { timingSafeEqual } from "https://deno.land/std/node/crypto.ts";
import { hmac } from "https://deno.land/x/hmac@v2.0.1/mod.ts";

const encoder = new TextEncoder()

const signature = req.headers.get(`x-hub-signature`) ?? ``;
const signatureBuffer = encoder.encode(signature);

const payload = await req.body({ type: `text` }).value;

const algorithm = signature.startsWith("sha256=") ? "sha256" : "sha1";

const verification = `${algorithm}=${hmac(algorithm, "helloworld", payload, "utf8", "hex")}`;
const verificationBuffer = encoder.encode(verification);

// constant time comparison to prevent timing attachs
// https://stackoverflow.com/a/31096242/206879
// https://en.wikipedia.org/wiki/Timing_attack
const matchesSignature = signatureBuffer.length === verificationBuffer.length
  && await timingSafeEqual(signatureBuffer, verificationBuffer);
rojvv commented

I already made it working with https://stackoverflow.com/a/71088170/10379728.