Webhook Signature Authentification
Verify the requests that Go1 sends to your webhook endpoints

In order to secure your webhook endpoints, which receive calls from Go1, Go1 can optionally sign the webhook events it sends to your endpoints by including a signature in each request’s header. This allows you to verify that the event requests were sent by Go1 and not by an unauthorized third party.

In order to activate the signature, create or update your webhook with a "secret_key" as described in our API Documentation. Note, the secret key length cannot exceed 64 characters.

After setting up a "secret_key" all requests made to your webhook endpoint will include a "Go1-Signature" value in the header. An example payload could look like this:

POST /webhooktest HTTP/1.1
Host: api.go1.com
Content-Length: 252
Content-Type: application/json
Go1-Signature: t=1588141753,v1=fa818dc59df5b5c7c42517dedf24d85ca2184201d03ed24bb6e2c7bf766b7e89
User-Agent: GO1 API v1.0

{"type":"user.create","fired_at":"2020-04-29T06:29:13+0000","data":{"id":"8191190","email":"new.user@go1.com","full_name":"New User","first_name":"New","last_name":"User","profile_picture":null,"status":null,"created_time":"1588141753","account":null}}

Additional Security - IP Range: The Go1 Platform is using the IP range 20.188.251.48/28 (Australia East) and 13.67.161.224/28 (Central US) for traffic from its Web/API fleet. This whole range is solely allocated to Go1. You can expect connections from webhooks to come from those IPs and allow them.

Webhook request signature verification

As you can see in the example above, the signature is included in the header:

Go1-Signature: t=1588141753,v1=fa818dc59df5b5c7c42517dedf24d85ca2184201d03ed24bb6e2c7bf766b7e89

The signature is made up of the component "t" , which is the timestamp when the signature has been created and the component "v1", which contains the signature itself. The "t" timestamp can be used to prevent replay attacks, by rejecting requests containing a timestamp which is too far in the past. The signature itself is generated using a hash-based message authentication code (HMAC) with the SHA-256 algorithm.

Step 1: Extract timestamp and signature from the request header

Split the header value of "Go1-Signature", using the "," character as the separator, to retrieve an array of components. Then split each component, using the "=" character as the separator, to get a key and value pair.

The value for the key t corresponds to the timestamp, and v1 corresponds to the signature.

Step 2: Calculate your own signature

Concatenate the following components to a string:

- The timestamp

- The "." character

- The JSON payload as a string

Using the example payload you should have string looking like this:

'1588141753.{"type":"user.create","fired_at":"2020-04-29T06:29:13+0000","data":{"id":"8191190","email":"new.user@go1.com","full_name":"New User","first_name":"New","last_name":"User","profile_picture":null,"status":null,"created_time":"1588141753","account":null}}'

Now use the "secret_key" which you have setup for this webhook earlier to compute an HMAC with the SHA256 hash function:

#PHP Example:
$calculatedSignature = hash_hmac('sha256', 'TIMESTAMP.JSON_PAYLOAD', 'MY_SECRET_KEY');

#Node.JS Example
const crypto = require("crypto");
let hmac = crypto.createHmac("sha256", 'MY_SECRET_KEY');
let calculatedSignature = hmac.update(Buffer.from('TIMESTAMP.JSON_PAYLOAD', 'utf-8')).digest("hex");

Step 3: Compare the received signature with your own

Compare the signature you have received in the request with the expected one which you calculated yourself. If they match, the request and payload come from a sender who knows your secret_key.