slackverifier

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2025 License: Unlicense Imports: 10 Imported by: 0

README

slackverifier

Go package to verify the authenticity of requests from Slack by validating their signatures and timestamps.

Usage

package main

import (
    "log"
    "net/http"
    "os"

    "github.com/andreswebs/slackverifier"
)

func main() {
    signingSecret := os.Getenv("SLACK_SIGNING_SECRET")
    if signingSecret == "" {
        log.Fatal("missing required environment variable SLACK_SIGNING_SECRET")
    }

    webhookHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // ...
        // add logic to process the request here
        // ...

        w.WriteHeader(http.StatusOK)
        return
    })

    // Wrap your handler with the Slack verification middleware
    http.Handle("/slack/webhook", slackverifier.SlackVerificationMiddleware(
        signingSecret,
        webhookHandler,
    ))

    log.Println("Server starting on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal(err)
    }
}

References

https://docs.slack.dev/authentication/verifying-requests-from-slack

https://github.com/slack-go/slack/issues/353

Acknowledgements

https://github.com/coro/verifyslack

AI Usage

Claude 3.5 Sonnet via GitHub Copilot was used to write documentation and tests for this package.

The text and the generated tests were thoroughly reviewed and updated by the author before publishing.

Authors

Andre Silva - @andreswebs

License

This project is licensed under the Unlicense.

Documentation

Overview

Package slackverifier provides functionality to verify incoming Slack webhook requests by validating their signatures against a signing secret.

Index

Constants

View Source
const (
	// SlackSignatureHeader is the HTTP header name containing the Slack signature.
	// This header contains the request signature used to verify the authenticity
	// of incoming webhook requests from Slack.
	SlackSignatureHeader string = "X-Slack-Signature"

	// SlackTimestampHeader is the HTTP header name containing the request timestamp.
	// This timestamp is used in conjunction with the signature to prevent replay attacks
	// by ensuring the request was made within an acceptable time window.
	SlackTimestampHeader string = "X-Slack-Request-Timestamp"
)

Variables

View Source
var (
	// ErrInvalidSignature is returned when the computed signature does not match
	// the signature provided in the Slack request header.
	ErrInvalidSignature = errors.New("invalid signature")

	// ErrMaxAllowedRequestAgeExceeded is returned when the request timestamp
	// is older than the configured MaxAllowedRequestAge duration.
	ErrMaxAllowedRequestAgeExceeded = errors.New("max allowed request age exceeded")
)

Functions

func GenerateSignature

func GenerateSignature(version string, timestamp string, data []byte, secret string) (sig string, err error)

GenerateSignature creates a Slack-compatible request signature using HMAC SHA256. The signature is generated by concatenating version:timestamp:body and using the signing secret as the HMAC key.

Parameters:

  • version: Slack signature version (defaults to "v0" if empty)
  • timestamp: Unix timestamp of the request
  • data: Raw request body bytes
  • secret: Slack signing secret used as HMAC key

Returns:

  • sig: Generated signature in format "v0=<hex(HMAC-SHA256(secret, message))>"
  • err: Error if HMAC operation fails

func SlackVerificationMiddleware

func SlackVerificationMiddleware(secret string, next http.Handler) http.Handler

SlackVerificationMiddleware creates an http.Handler that verifies incoming Slack webhook requests. It checks the request signature and timestamp to ensure the request is authentic and recent.

The middleware performs the following checks: - Validates presence of required Slack headers (X-Slack-Signature and X-Slack-Request-Timestamp) - Ensures the request uses POST method - Verifies the request signature against the signing secret - Checks if the request timestamp is within the allowed time window

If any check fails, the middleware responds with an appropriate HTTP status code: - 400 Bad Request: missing headers or invalid request body - 405 Method Not Allowed: non-POST requests - 401 Unauthorized: invalid signature or expired timestamp

Parameters:

  • secret: The Slack signing secret used to verify request signatures
  • next: The handler to call if all verification checks pass

Returns an http.Handler that wraps the provided handler with Slack verification.

Types

type SlackRequestData

type SlackRequestData struct {
	// Version is the signature version used by Slack (defaults to "v0")
	Version string
	// RawBody is the raw request body bytes from the webhook
	RawBody []byte
	// SlackSignature is the signature provided in the X-Slack-Signature header
	SlackSignature string
	// Timestamp is the request timestamp from X-Slack-Request-Timestamp header
	Timestamp string
	// SigningSecret is the Slack application's signing secret
	SigningSecret string
	// MaxAllowedRequestAge specifies the maximum time window during which a request is considered valid
	MaxAllowedRequestAge time.Duration
}

SlackRequestData contains all necessary information to verify a Slack webhook request.

func (SlackRequestData) IntTimestamp

func (s SlackRequestData) IntTimestamp() (ts int64, err error)

IntTimestamp converts the request's timestamp string to an int64 Unix timestamp. Returns an error if the timestamp string cannot be parsed as a base-10 integer.

func (SlackRequestData) VerifySignature

func (s SlackRequestData) VerifySignature() (ok bool, err error)

Verify checks if the request is authentic by comparing the provided signature with a computed signature using the signing secret. It returns true if the signatures match, indicating the request is valid and came from Slack.

The signature is computed using HMAC SHA256 with the following format: v0=<hex(HMAC-SHA256(signing_secret, v0:timestamp:body))>

func (SlackRequestData) VerifyTimestamp

func (s SlackRequestData) VerifyTimestamp() (ok bool, err error)

VerifyTimestamp checks if the request's timestamp is within the allowed time window. It returns true if the request is not too old, and false with an error if the request has exceeded the MaxAllowedRequestAge. If MaxAllowedRequestAge is not set, it defaults to 60 seconds.

This check helps prevent replay attacks by ensuring requests are recent enough to be valid.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL