Skip to content

Instantly share code, notes, and snippets.

@phistrom
Last active December 4, 2022 16:40
Embed
What would you like to do?
Function to verify X-Slack-Signature header in a Cloudflare Worker
/* global SLACK_SIGNING_SECRET */
const SIGN_VERSION = 'v0' // per documentation, this is always "v0"
/**
* Verify that a request actually came from Slack using our Signing Secret
* and HMAC-SHA256.
*
* Based on code examples found in Cloudflare's documentation:
* https://developers.cloudflare.com/workers/examples/signing-requests
*
* @param {Request} request incoming request purportedly from Slack
* @returns {Promise<boolean>} true if the signature verification was valid
*/
export async function verifySlackSignature(request) {
const timestamp = request.headers.get('x-slack-request-timestamp')
// remove starting 'v0=' from the signature header
const signatureStr = request.headers.get('x-slack-signature').substring(3)
// convert the hex string of x-slack-signature header to binary
const signature = hexToBytes(signatureStr)
const content = await request.text()
const authString = `${SIGN_VERSION}:${timestamp}:${content}`
let encoder = new TextEncoder()
const key = await crypto.subtle.importKey(
'raw',
encoder.encode(SLACK_SIGNING_SECRET),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['verify']
)
const verified = await crypto.subtle.verify(
"HMAC",
key,
signature,
encoder.encode(authString)
)
return verified
}
/**
* Modified version of hex to bytes function posted here:
* https://stackoverflow.com/a/34356351/489667
*
* @param {string} hex a string of hexadecimal characters
* @returns {ArrayBuffer} binary form of the hexadecimal string
*/
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let c = 0; c < hex.length; c += 2) {
bytes[c / 2] = parseInt(hex.substr(c, 2), 16);
}
return bytes.buffer
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment