Webhook Verification
Webhooks sent by Northpass can be verified by calculating a digital signature.
Each Webhook request includes an X-Northpass-Hmac-SHA256
header which is generated using your school’s shared secret, along with the data sent in the body of the request.
To verify that the request came from Northpass, compute the HMAC digest according to the following algorithm and compare it to the value in the X-Northpass-Hmac-SHA256
header. If they match, you can be sure that the Webhook was sent from Northpass and the data has not been compromised.
Note
If you are using a Rack-based framework such as Ruby on Rails or Sinatra, the header you are looking for is
HTTP_X_Northpass_Hmac_SHA256
Sample Application
Here's an example of how one might verify a webhook request:
require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'
# The Northpass app's shared secret, viewable from the Webhooks app
SHARED_SECRET = 'my_shared_secret'
helpers do
# Compare the computed HMAC digest based on the shared secret and the request contents
# to the reported HMAC in the headers
def verify_webhook(data, hmac_header)
digest = OpenSSL::Digest::Digest.new('sha256')
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, SHARED_SECRET, data)).strip
calculated_hmac == hmac_header
end
end
# Respond to HTTP POST requests sent to this web service
post '/' do request.body.rewind
data = request.body.read
verified = verify_webhook(data, env["HTTP_X_Northpass_Hmac_SHA256"])
# Output 'true' or 'false'
puts "Webhook verified: #{verified}"
end
from flask import Flask, request
import base64
import hashlib
import hmac
app = Flask(__name__)
# The Northpass app's shared secret, viewable from the Webhooks app
SHARED_SECRET = b'my_shared_secret' # The secret should be bytes
# Compare the computed HMAC digest based on the shared secret and the request contents
# to the reported HMAC in the headers
def verify_webhook(data, hmac_header):
hmac_obj = hmac.new(SHARED_SECRET, data, hashlib.sha256)
calculated_hmac = base64.b64encode(hmac_obj.digest()).decode().strip()
return calculated_hmac == hmac_header
# Respond to HTTP POST requests sent to this web service
@app.route('/', methods=['POST'])
def webhook():
# Rewind and read the request body
data = request.data
# Retrieve the HMAC from the headers
hmac_header = request.headers.get('X-Northpass-Hmac-SHA256', '')
# Verify the webhook
verified = verify_webhook(data, hmac_header)
# Print and return the result
print(f"Webhook verified: {verified}")
return f"Webhook verified: {verified}"
if __name__ == '__main__':
app.run(debug=True)
Updated 8 months ago