SaaSquatch Help Center

Signed Requests provide a layer of security for the squatch.js javascript library to validate that the data we receive originated from your servers.

Whether Signed Requests are required can be configured using the Secure Mode settings.

Secure Mode Settings

The Secure Mode settings determine which, if any, of the squatch.js Methods are required to be signed using a JWT when connecting to the SaaSquatch system. The configuration settings for Secure Mode can be found on the Install page in the SaaSquatch Admin Portal.

The available settings for Secure Mode include Enabled, Disabled, and Custom.

Secure Mode Enabled

Secure Mode Enabled

With Secure Mode enabled calls made using our squatch.js library are required to be signed with a JWT to verify the contents of the request.

Secure Mode Disabled

Turning Secure Mode off allow you to make request to the SaaSquatch System through the squatch.js library without them needing to be signed with a JWT.

We highly recommend using Signed Requests to reduce your referral program's exposure to a man-in-the-middle security vulnerability. With Signed Requests turned off more attention should be paid to your incoming referrals. We recommend keeping a close watch on incoming referrals and familiarize yourself with how our referral Security Management System functions.

Custom Secure Mode Settings

The Custom configuration for Secure Mode allow for granular control over which squatch.js methods are required to be signed with a JWT.

Custom Secure Mode

Notable Settings
Custom Secure Mode Option Description
Create/Update User Enable/Disable the ability to create or update Users in the SaaSuqatch system without including a JWT
Create/Update Anonymous User Enable/Disable the ability to Display the Unregistered User Widget without including a JWT

When to Use Signed Requests

Certain referral program functionality is limited based on the type of referral program you have and the state of the Signed Requests setting.

The follow charts outline the security requirements for different program types and Signed Request settings.

API Programs

For referral programs configured as "API-only":

Signed Requests ON Signed Requests OFF
payment_provider_id included Checksum/JWT Required No Checksum/JWT
payment_provider_id null Checksum/JWT Required No Checksum/JWT

Payment Provider Programs

For referral programs configured for one of our Payment Provider Integrations:

Signed Requests ON Signed Requests OFF
payment_provider_id included Checksum/JWT Required No Checksum/JWT
payment_provider_id null Checksum/JWT Required Checksum/JWT Required

How do I use signed requests?

A signed request uses either a cryptographic signature (checksum) or a JSON Web Token (JWT).

To use signed requests, your server must generate a JWT or checksum using your tenant's API key, and pass that to the squatch.js init function.

JWT

The JWT will be used to sign the data that you plan to submit to Referral SaaSquatch.

Building the JWT

The JWT payload is built using the JSON object of the squatch.js init parameters:

Note: Make sure ignore client-only parameters like mode

{
  "tenant_alias": "test_aaaexampleaaa",
  "account_id": "a5678",
  "payment_provider_id": null,
  "user_id": "u1234",
  "email": "joe.tester@example.com",
  "first_name": "Joe",
  "last_name": "Tester",
}

The process for building the JWT is outlined on our JSON Web Tokens page.

Checksum

How do I generate a checksum?

The param checksum is computed using a HMAC-SHA2 algorithm. The signed value is a concatenated string assembled from the squatch.js init parameter map. As a simple convention, the values are concatenated based on an alphabetical ordering of the parameter names. This will become more clear in an example below. The final piece missing is the HMAC algorithm’s shared secret: your account’s API key.

Don't forget! You have a both a live API key and a test API key.

Example: Generating a Checksum

To start using secure requests, you simply need to add a checksum. For example, here is a JSON object of the parameters to be signed:

{
    "tenant_alias": "test_aaaexampleaaa",
    "account_id": "a5678",
    "payment_provider_id": null,
    "user_id": "u1234",
    "email": "joe.tester@example.com",
    "first_name": "Joe",
    "last_name": "Tester",
    "mode": "EMBED",
    "locale": "en_US"
}
  1. Ignore client-only parameters that don't need to be signed. The mode, locale parameters should be ignored.

    {
      "tenant_alias": "test_aaaexampleaaa",
      "account_id": "a5678",
      "payment_provider_id": null,
      "user_id": "u1234",
      "email": "joe.tester@example.com",
      "first_name": "Joe",
      "last_name": "Tester",
      //"mode": "EMBED",
      //"locale": "en_US"
    }
    
  2. Sort your parameters according to the alphabetical order of their keys. Notice how account_id is now first and user_id is now last.

    {
      "account_id": "a5678", // <-- "a" is sorted to first
      "email": "joe.tester@example.com",
      "first_name": "Joe",
      "last_name": "Tester",
      "payment_provider_id": null,
      "tenant_alias": "test_aaaexampleaaa",
      "user_id": "u1234" // <-- "u" is sorted to last
    }
    
  3. Concatenate the sorted values. Starting with an empty string, iterate through all the parameters that you sorted and append each parameter's value to the end of a string. Notice how "a5678", the value for account_id, is at the start, and "u1234", the value for user_id, is at the end. Also, any optional parameters or null parameters can be omitted. In this example payment_provider_id is set to null and isn't included in the concatenated string.

    a5678joe.tester@example.comJoeTestertest_aaaexampleaaau1234
    ^^^ the value for accountId is first
  4. Sign the string using your API key to compute a HMAC-SHA2 checksum. In the code below we use an example API key: TEST_HGO8125ANDFH152HSAS15

    using System.Security.Cryptography;
    
    private string CreateToken(string message, string secret)
        {
        var encoding = new System.Text.ASCIIEncoding();
        byte[] keyByte = encoding.GetBytes(secret);
        byte[] messageBytes = encoding.GetBytes(message);
        using (var hmacsha256 = new HMACSHA256(keyByte))
        {
            byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
            return Convert.ToBase64String(hashmessage);
        }
    }
    require 'openssl'
    require base64'
    
    hash = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', 'TEST_HGO8125ANDFH152HSAS15', 'a5678joe.tester@example.comJoeTestertest_aaaexampleaaau1234'))
    import java.security.SignatureException;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    
    public static String calculateHMACSHA256(String data, String secretKey) throws java.security.SignatureException {
        String result;
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
            mac.init(key);
            byte[] authentication = mac.doFinal(data.getBytes());
            result = new String(org.apache.commons.codec.binary.Base64.encodeBase64(authentication));
    
        } catch (Exception e) {
            throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
        }
        return result;
    }
    base64_encode(hash_hmac('sha256','a5678joe.tester@example.comJoeTestertest_aaaexampleaaau1234', 'TEST_HGO8125ANDFH152HSAS15', true))
    import hashlib
    import hmac
    import base64
    
    message = bytes('a5678joe.tester@example.comJoeTestertest_aaaexampleaaau1234').encode('utf-8')
    secret = bytes('TEST_HGO8125ANDFH152HSAS15').encode('utf-8')
    base64.standard_b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest())

  5. Include the checksum in your javascript initialization call. Secure mode is enabled for an account as soon as we receive your first valid signed request. Once enabled, non-signed requests will no longer be accepted for that account.

    
    _sqh.push(['init', {
      tenant_alias: 'test_aaaexampleaaa',
      account_id: 'a5678',
      payment_provider_id: null,
      user_id: 'u1234',
      email: 'joe.tester@example.com',
      first_name: 'Joe',
      last_name: 'Tester'
      checksum: 'TFs5pf1zQUgaerOVvLSIiCfrty/GXHdXU5AK5rCmbYU=' // <-- Add the checksum to your init call
    }]);