SaaSquatch Help Center

JSON Web Tokens are used as part of Signed Requests with squatch.js and Open Endpoints. They are used to validate the data being supplied to Referral SaaSquatch.

🔗 What is a JWT?

A JWT is an open standard for securely sharing information as a JSON object. JWTs are small enough to be used in a GET or POST parameter or an HTTP header and because they are digitally signed the information inside can be trusted. This allows us to use a JWT like a checksum to verify that the squatch.js init parameters are correct, but with the convenience of using a library to generate the JWT.

🔗 How do I generate a JWT?

JWTs can easily be generated using one of the libraries available. There are even more libraries in even more languages available on GitHub in addition to the ones recommended by JWT.io.

🔗 Example: Building the JWT

🔗 1. Collect the Data Object

Whether you are using a JWT with squatch.js or the Open Endpoints you will need to start with the data object that you are trying to sign.

For Open Endpoint and squatch.js calls the data might look like:

{
    "id": "abc_123",
    "accountId": "abc_123",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com",
    "locale": "en_US",
    "referralCode": "JOHNDOE"
}

🔗 2. Assemble the JWT payload

The JWT payload structures the data trying to be signed as follows:

Please Note: Do not include tenantAlias in the JWT payload for squatch.js.

For Open Endpoint and squatch.js calls:

{
  "user":{
    "id": "abc_123",
    "accountId": "abc_123",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com",
    "locale": "en_US",
    "referralCode": "JOHNDOE"
  }
}

🔗 3. Sign the Payload

Use your chosen library to build the JWT with the payload, and sign it with your tenant's API key.

Test mode vs. live mode - Your SaaSquatch program provides both a live and test mode. Each of these tenants provides an independant API key. Make sure to use the correct API key for call you are trying to sign.

using System.Collections.Generic;
    using System.Text;
    using Jose;

    namespace JWTExample
    {
        class Program
        {
            public static string buildJWT(string secret, string accountId, string userId, string email, string firstName, string lastName, long expiryDate, string referralCode)
            {
                var userPayload = new Dictionary<string, object>()
                {
                  { "id", userId },
                  { "accountId", accountId },
                  { "firstName", firstName },
                  { "lastName", lastName },
                  { "email", email },
                  { "locale", locale },
                  { "referralCode", referralCode }
                };

                var payload = new Dictionary<string, object>()
                {
                  { "user", userPayload },
                  { "exp", expiryDate } //optional date in seconds since the epoch
                };

                //the encoding must match the encoding of your secret, UTF8 is just an example
                var byteSecret = Encoding.UTF8.GetBytes(secret);

                return Jose.JWT.Encode(payload, byteSecret, JwsAlgorithm.HS256);
            }
        }
    }
require 'jwt'

    def buildJWT(secret, userId, accountId, email, firstName, lastName, referralCode, locale, expiryDate)
        secret = 'Referral SaaSquatch API key'
        return payload = JWT.encode({
        user: {
          id: userId,
          accountId: accountId,
          firstName: firstName,
          lastName: lastName,
          email: email,
          locale: locale,
          referralCode: referralCode
        },
        exp: expiryDate #optional date in seconds since the epoch
        }, secret)
    end
import java.util.HashMap;
import java.util.Map;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

public class JWTExample {

    public static String buildJWT(String secret, String accountId, String userId, String email,
            String firstName, String lastName, Long expiryDate, String referralCode, String userReferralCode, String locale,
            String accountStatus, String userImage) {
        // build user object
        final Map<String, Object> userMap = new HashMap<String, Object>();
        userMap.put("id", userId);
        userMap.put("accountId", accountId);
        userMap.put("firstName", firstName);
        userMap.put("lastName", lastName);
        userMap.put("email", email);
        userMap.put("locale", locale);
        userMap.put("referralCode", referralCode);

        // standard header
        final JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256)
                .type(JOSEObjectType.JWT)
                .build();
        final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                .claim("user", userMap)
                .claim("exp", expiryDate) // optional nullable date in seconds since the epoch
                .build();
        final SignedJWT jwt = new SignedJWT(header, claimsSet);
        try {
            jwt.sign(new MACSigner(secret));
        } catch (JOSEException e) {
            // This will happen if your secret is shorter than 256 bits.
            // If you are using your tenant API key, you won't need to worry about it.
            throw new RuntimeException(e);
        }
        return jwt.serialize();
    }
}
use \Firebase\JWT\JWT;

    function buildJWT($secret, $userId, $accountId, $email, $firstName, $lastName, $locale, $referralCode) {
        //build user object
        $payload = array(
        "user" => array(
          "id" => $userId,
          "accountId" => $accountId,
          "firstName" => $firstName,
          "lastName" => $lastName,
          "email" => $email,
          "locale" => $locale,
          "referralCode" => $referralCode,
        ),
        "exp" => $expiryDate //optional date in seconds since the epoch
        );

        //the encoder defaults to HS256, no need to specify an algorithm
        return JWT::encode($payload, $secret);
    }
import jwt

    def buildJWT(secret, userId, accountId, email, firstName, lastName, locale, referralCode, expiryDate):
    return jwt.encode({
    'user': {
        'id': userId,
        'accountId': accountId,
        'firstName': firstName,
        'lastName': lastName,
        'email': email,
        'locale': locale,
        'referralCode': referralCode
    },
    'exp': expiryDate #optional date in seconds since the epoch
    }, secret, algorithm='HS256')

🔗 4. Include the JWT

🔗 squatch.js

Once you have created the JWT, be sure to include it with all of your calls. An example of a squatch.js call including the JWT is included below:


window.squatch.ready(function(){

  //configure squatch.js for the tenant you are using
squatch.init({ tenantAlias: 'test_abzxg88g30tn2' }); //object containing the init parameters for squatch.js var initObj = { //the object for the user you want to upsert user: {
id: 'abc_123',
accountId: 'abc_123',
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe', referable: false }, engagementMedium: 'EMBED', widgetType: 'REFERRER_WIDGET', jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiYWJjXzEyMyIsImFjY291bnRJZCI6ImFiY18xMjMiLCJlbWFpbCI6ImpvaG5AZXhhbXBsZS5jb20iLCJmaXJzdE5hbWUiOiJKb2huIiwibGFzdE5hbWUiOiJEb2UiLCJyZWZlcmFibGUiOmZhbHNlfX0.ZomcuXZxyI1vhf94q2ipByj6WVMsik1OgLxaDBke0Pg' }; squatch.widgets().upsertUser(initObj).then(function(response) { user = response.user; }).catch(function(error){ console.log(error); }); });

window.squatch.ready(function(){

  //configure squatch.js for the tenant you are using
squatch.init({ tenantAlias: 'test_abzxg88g30tn2' }); //object containing the init parameters for squatch.js var initObj = { //the object for the user you want to upsert user: {
id: 'abc_123',
accountId: 'abc_123',
email: 'john@example.com',
firstName: 'John',
lastName: 'Doe', referable: false }, engagementMedium: 'EMBED', widgetType: 'p/program-name/w/referrerWidget', jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiYWJjXzEyMyIsImFjY291bnRJZCI6ImFiY18xMjMiLCJlbWFpbCI6ImpvaG5AZXhhbXBsZS5jb20iLCJmaXJzdE5hbWUiOiJKb2huIiwibGFzdE5hbWUiOiJEb2UiLCJyZWZlcmFibGUiOmZhbHNlfX0.ZomcuXZxyI1vhf94q2ipByj6WVMsik1OgLxaDBke0Pg' }; //update/register a referral participant and display a widget squatch.widgets().upsertUser(initObj).then(function(response) { user = response.user; }).catch(function(error){ console.log(error); }); });
🔗 Open Endpoint API Call

Note - Open Endpoint API calls made from a server should be signed with your tenant's API key. Only Open Endpoint calls from a client should be signed with a JWT.

For use with an Open Endpoint API call the JWT should be included in the API call as a header with the key X-SaaSquatch-User-Token.

cURL uses the -H flag to pass an extra header. You may specify any number of extra headers.

curl -X POST https://app.referralsaasquatch.com/api/v1/{tenant_alias}/open/account/{accountId}/user/{userId} \
-H "X-SaaSquatch-User-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoidTEyMzQiLCJhY2NvdW50SWQiOiJhNTY3OCIsImVtYWlsIjoiam9lQGV4YW1wbGUuY29tIiwiZmlyc3ROYW1lIjoiSm9lIiwibGFzdE5hbWUiOiJUZXN0ZXJzb24iLCJsb2NhbGUiOiJlbl9VUyIsInJlZmVycmFsQ29kZSI6IkpPRVRFU1RFUlNPTiJ9fQ.TymCGn2W7H_QGwVqX4k5ELB7HS04RfRSpDATAsl67zI" \
-H "Content-Type: application/json" \
-d '{
    "id": "u1234",
    "accountId": "a5678",
    "email": "Joe@example.com",
    "firstName": "Joe",
    "lastName": "Testerson",
    "locale": "en_US",
    "referralCode": "JOETESTERSON"
}'

🔗 Additional Resources

Read more about Signed Requests for squatch.js and Open Endpoints. This article covers case-specific details about parameters to exclude and how to add a JWT to a call.