JSON Web Tokens (JWTs)

A JSON Web Token, or 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.

JWTs can be generated using a library. Options can be found on JWT.io or GitHub.

Step 1: Collect the data object

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

For Advocate implementations, id and accountId will always be set to the same thing.

{  
    "id": "[email protected]", //This field will be dependent on your implementation
    "accountId": "[email protected]", //This field will be dependent on your implementation
    "firstName": "John",  
    "lastName": "Doe",  
    "email": "[email protected]",  
    "locale": "en_US",    
}

Step 2: Assemble the JWT payload

The JWT payload structures the data trying to be signed in this format:

For Advocate implementations, id and accountId will always be set to the same thing.

{  
  "user":{  
    "id": "[email protected]", //This field will be dependent on your implementation
    "accountId": "[email protected]", //This field will be dependent on your implementation
    "firstName": "John",  
    "lastName": "Doe",  
    "email": "[email protected]",  
    "locale": "en_US",    
  }  
}

Step 3: Sign the payload

Use your chosen library to build the JWT with the payload, and sign it with your API key and Auth Token.

// Example uses jose-jwt: https://github.com/dvsekhvalnov/jose-jwt

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

namespace JwtExample
{
  class Jwt
  {
    // An example for building a user JWT.
    //   accountSid/authToken - your impact.com API credentials
    //   userId - your unique identifier for this user
    public static string buildJwt(string accountSid, string authToken, string userId, string email, string firstName, string lastName)
    {
      // Build the user payload. Most fields are optional, but id and accountId are required 
      // and are set to the same value. See the API documentation for more fields that you 
      // can add to your users.
      var userPayload = new Dictionary<string, object>() {
        { "id", userId },           // required
        { "accountId", userId },    // required
        { "firstName", firstName }, // optional
        { "lastName", lastName },   // optional
        { "email", email }          // optional
      };

      // Expiry date is optional, but recommended
      var expiryDate = ((DateTimeOffset)DateTime.UtcNow.Date.AddDays(7)).ToUnixTimeSeconds();

      var payload = new Dictionary<string, object>() {
        { "user", userPayload },
        { "exp", expiryDate }
      };

      var headers = new Dictionary<string, object>() {
        { "typ", "JWT" },
        { "kid", accountSid }
      };

      var byteSecret = Encoding.UTF8.GetBytes(authToken);

      return Jose.JWT.Encode(payload, byteSecret, JwsAlgorithm.HS256, extraHeaders: headers);
    }
  }
}
# Example uses ruby-jwt: https://github.com/jwt/ruby-jwt

require "jwt"

# An example for building a user JWT.
#   accountSid/authToken - your impact.com API credentials
#   userId - your unique identifier for this user
def buildJwt(accountSid, authToken, userId, email, firstName, lastName)

  # Build the user payload. Most fields are optional, but id and accountId are required
  # and are set to the same value. See the API documentation for more fields that you
  # can add to your users.
  userPayload = {
    id: userId,            # required
    accountId: userId,     # required
    firstName: firstName,  # optional
    lastName: lastName,    # optional
    email: email,          # optional
  }

  # Expiry date is optional, but recommended
  expiryDate = Time.now.to_i + 7 * 24 * 3600

  payload = {
    user: userPayload,
    exp: expiryDate,
  }

  headers = {
    typ: "JWT",
    kid: accountSid,
  }

  return JWT.encode(payload, authToken, algorithm = "HS256", header_fields = headers)
end
// Example uses nimbus-jose-jwt: https://bitbucket.org/connect2id/nimbus-jose-jwt/src/master/

import java.time.Duration;
import java.time.Instant;
import java.util.Date;
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 Jwt {

	// An example for building a user JWT.
	//   accountSid/authToken - your impact.com API credentials
	//   userId - your unique identifier for this user
	public static String buildJwt(String accountSid, String authToken, String userId, String email, String firstName, String lastName) {
	
		// Build the user payload. Most fields are optional, but id and accountId are required 
		// and are set to the same value. See the API documentation for more fields that you 
		// can add to your users.
		final Map<String, Object> userPayload = new HashMap<>();
		userPayload.put("id", userId);           // required
		userPayload.put("accountId", userId);    // required
		userPayload.put("firstName", firstName); // optional
		userPayload.put("lastName", lastName);   // optional
		userPayload.put("email", email);         // optional
												 
        // Expiry date is optional, but recommended
		Date expiryDate = Date.from(Instant.now().plus(Duration.ofDays(7)));

		final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
				.claim("user", userPayload)
				.expirationTime(expiryDate)
				.build();

		final JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256)
				.type(JOSEObjectType.JWT)
				.keyID(accountSid)
				.build();

		final SignedJWT jwt = new SignedJWT(header, claimsSet);

		try {
			jwt.sign(new MACSigner(authToken));
		} catch (JOSEException e) {
			// This will happen if your secret is shorter than 256 bits.
			// If you are using your Impact API keys, you won't need to worry about it.
			throw new RuntimeException(e);
		}

		return jwt.serialize();
	}

}
// Example uses php-jwt: https://github.com/firebase/php-jwt

use Firebase\JWT\JWT;

// An example for building a user JWT.
//   accountSid/authToken - your impact.com API credentials
//   userId - your unique identifier for this user
function buildJwt($accountSid, $authToken, $userId, $email, $firstName, $lastName)
{
    // Build the user payload. Most fields are optional, but id and accountId are required 
    // and are set to the same value. See the API documentation for more fields that you 
    // can add to your users.
    $userPayload = [
        "id" => $userId,           // required
        "accountId" => $userId,    // required
        "firstName" => $firstName, // optional
        "lastName" => $lastName,   // optional
        "email" => $email,         // optional
    ];
    
    // Expiry date is optional, but recommended
    $now = new DateTime();
    $expiryDate = $now->add(new DateInterval('P7D'))->getTimestamp();

    $payload = [
        "user" => $userPayload,
        "exp" => $expiryDate
    ];
    
    $headers = [
        "typ" => "JWT",
        "kid" => $accountSid
    ];

    return JWT::encode($payload, $authToken, 'HS256', null, $headers);
}
# Example uses PyJWT: https://github.com/jpadilla/pyjwt/

import time
import jwt

# An example for building a user JWT.
#   accountSid/authToken - your impact.com API credentials
#   userId - your unique identifier for this user
def buildJwt(accountSid, authToken, userId, email, firstName, lastName):

    # Build the user payload. Most fields are optional, but id and accountId are required 
    # and are set to the same value. See the API documentation for more fields that you 
    # can add to your users.
    userPayload = {
        'id': userId,           # required
        'accountId': userId,    # required
        'firstName': firstName, # optional
        'lastName': lastName,   # optional
        'email': email          # optional
    }
    
    # Expiry date is optional, but recommended
    expiryDate = time.time() + 7 * 24 * 3600
    
    payload = {
        'user': userPayload,
        'exp': expiryDate
    }

    headers = {
        'typ': 'JWT',
        'kid': accountSid
    }
    
    return jwt.encode(payload, authToken, algorithm='HS256', headers=headers)

For other fields that can be included in user objects, visit the User Upsert API documentation.

Step 4: Include the JWT with your calls

After creating a JWT, it must be included with all of your calls.

UTT

Here’s an example of how a UTT call that includes the JWT would appear:

<script>    
window.impactToken = “JWT_GOES_HERE”  
</script>
<impact-embed widget=”p/program-id/w/referrerWidget”></impact-embed>

Open Endpoint API Call

For Open Endpoint API calls, the JWT must be included 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.

🚧

Note:

Open Endpoint API calls made from a server should be signed with your API key. Only Open Endpoint calls from a client should be signed with a JWT.

curl -X POST <https://app.referralsaasquatch.com/api/v1/{tenant_alias}/open/account/{accountId}/user/{userId}>   
-H "X-SaaSquatch-User-Token: {X-SaaSquatch-User-Token}"   
-H "Content-Type: application/json"   
-d '{  
    "id": "[email protected]",  
    "accountId": "[email protected]",  
    "email": "[email protected]",  
    "firstName": "Joe",  
    "lastName": "Testerson",  
    "locale": "en_US",  
    "referralCode": "JOETESTERSON"  
}'