Project

actionhook

0.0
No release in over 3 years
Low commit activity in last 3 years
Use this library to send webhooks from your application
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
 Project Readme

Why?

ActionHook is a drop-in ruby gem for sending webhooks. You specify the content and destination, ActionHook takes care of securely delivering it.

Sending a webhook from an application starts out as a simple coding task. To put webhooks into production is actually quite complex because you need to worry about timeouts, retry, TLS issues, authentication, and secure delivery. Scaling webhooks can be a challenge if you have to send thousands of such hooks every second. This library is designed with these features in mind and should work for most use cases.

Build Status

Ruby

Features

  • Core Send webhooks
  • Configuration Timeout, IP blocking, etc.
  • Security Supports HTTP Basic, Token, and Bearer Token auth
  • Security Blocks private IPs and allows custom IP blocking
  • Security 2-factor authentication using a secret for each receiver
  • Usability Works seamlessly on Ruby on Rails. Example
  • Scale Works seamlessly on AWS Lambda. Example
  • More Logging

Send Webhooks

request = ActionHook::Core::JSONRequest.new(url: 'https://example.com',
  method: :post, body: { hello: "world" }, headers: {})

ActionHook::Core::NetHTTPSender.send(request)

Configuration

All configs are optional, only use these if you want to override the defaults. You can set the following configs in ActionHook.configuration object.

Name Description Default Value
open_timeout Net::HTTP open timeout in seconds 5
read_timeout Net::HTTP read timeout in seconds 15
hash_header_name A HTTP Request header that contains the SHA256 fingerprint of the request body SHA256-FINGERPRINT
allow_private_ips If loopback or private IPs should be allowed as receiver false
blocked_ip_ranges Custom IP ranges to block, e.g. %w{172.8.9.8/24} []

Instead of ActionHook.configuration, you can provide an instance of ActionHook::Core::Configuration to the send method as follows:

ActionHook::Core::NetHTTPSender.send(request, ActionHook::Core::Configuration.new)

Security: Authentication

ActionHook supports Basic, Token, and BearerToken authentication out of the box. You can assign one of these authentication methods to the request object as follows:

  basic = ActionHook::Security::Authentication::Basic.new(username: 'a_user', password: 'a_pass')
  token = ActionHook::Security::Authentication::Token.new('a_token')
  bearer_token = ActionHook::Security::Authentication::BearerToken.new('a_bearer_token')

  request = ActionHook::Core::JSONRequest.new(url: 'https://example.com',
    authentication: basic, # or token, bearer_token
  )

Security: 2-Factor Authentication: Hashing With a Secure Key

You can generate a secure key for each receiving endpoint and pass it to ActionHook for adding a 2nd factor authentication. Using this key, ActionHook will automatically add the SHA256-FINGERPRINT header to the webhook. The receiver can compute the SHA256 digest of the request body using the same secret to verify you as the sender and message integrity.

request = ActionHook::Core::JSONRequest.new(url: 'https://example.com',
  secret: '<Your Secret For This Hook>', # Remember to provide your secret
  method: :post, body: { hello: "world" }, headers: {})

ActionHook::Core::NetHTTPSender.send(request)

Security: IP Blocking

When a request is blocked due to private IP receiver, send raises ActionHook::Security::IPBlocking::PrivateIPError.

When a request is blocked due to the blocked_ip_ranges, send raises ActionHook::Security::IPBlocking::BlockedRequestError.

In both cases, the error message includes necessary context for debugging / logging.

Logging

You should pass an instance of Logger to put all ActionHook logs into where your application log is. Otherwise, logs are written into STDOUT by default.

# For example, in Rails, you can pass the Rails logger in an initializer
# config/initializers/actionhook_initializer.rb

ActionHook.logger = Rails.logger

Set the log level to debug for detailed information. Even in debug, the secure header values aren't logged for accidental credential leakage, only the header names are mentioned.

Develop and Contribute

# Install dependencies
$ bundle

# Run tests
$ bundle exec rspec

Make your changes on a fork and send a pull-request when you're ready. Include details about the intent and how you tested your changes.

Works great on GitHub Codespaces, too.