Skip to content

Instantly share code, notes, and snippets.

@phistrom
Last active September 22, 2023 19:34
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phistrom/3d691a2b4845f9ec9421faaebddc0904 to your computer and use it in GitHub Desktop.
Save phistrom/3d691a2b4845f9ec9421faaebddc0904 to your computer and use it in GitHub Desktop.
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
}
@kevbook
Copy link

kevbook commented Sep 22, 2023

substr is deprecated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment