How to Secure the Web API with Identity Verification

You can enable enhanced security for Prefinery's javascript snippet (and therefore the JavaScript Web API) by enforcing identity verification. Identity verification protects your customer’s information, and prevents bad actors from making guesswork or brute-force calls to the JavaScript Web API in order to phish personal information from users that may exist in your campaign. 

With this feature enabled, some Web API calls will require a signature to accompany the request to ensure its validity. Optionally, the user can be authenticated with the current browser session first so subsequent requests will each no longer require a signature until the user closes their browser. 

Enabling Identity Verification

Identity Verification is enabled by default, but if you want to make sure that it is (in case you or a team member may have disabled it before) here's how you can enable it: 

We strongly recommend that you enforce identity verification.

1

From your project dashboard, navigate to Settings > Project Settings > General Settings

2

Scroll down and you should find the Enforce Identity Verification option. Turn it ON if it isn't yet and copy your Identity Verification Secret key. 

3

Proceed to the next sections below for more information on how to use your Identity Verification Secret key in generating a signature for Web API calls.    

Utilizing Identity Verification

Option 1: Authenticate the User

Call the authenticateUser function in order to authenticate the user into their current browser session (e.g. drop an authentication cookie) so that you do not have to provide a signature to each subsequent API request. This authentication will last until the user closes their browser.

Note: This is automatically done for you after adding a new user as part of the addUser function.

prefinery('authenticateUser', {
  email: 'bruce@wayneenterprises.com',
  signature: 'd1d2c2be5bd802b8625f5fabf274a7f65c11b89a6bb426e74161d79cb9f0e7f2'
}, function() {
  prefinery('getUser', {
    email: 'bruce@wayneenterprises.com',
  }, function(user) {
    console.log('User: ' + JSON.stringify(user));
  });
});

Option 2: Pass a Signature to Each Request

When making calls to the JavaScript Web API with Identity Verification enabled you will be required to pass a signature. The  signature is a generated SHA-256 HMAC of the combination of either the user's email address, referral code, or id, and your project's identity verification secret key. You should calculate this signature server-side (not client-side).

As an example, let's take the getUser function. To look up a user by email address, we'd use:

prefinery('getUser', {
  email: 'participant@email.com',
  signature: '8c1fea388d4ac3415adfa7c09a38d355855809ec5a473d54adfa1d708027907e'
}, function(user) {
  console.log('User: ' + JSON.stringify(user));
});

Where:

  • [Value to Compute Hash]: participant@email.com
  • [Identity Verification Secret Key]: aBc123DeF456gHi789JkL012mNo345PqR678sTu901Vw
  • Hashed Output / Signature: 8c1fea388d4ac3415adfa7c09a38d355855809ec5a473d54adfa1d708027907e

In this case, since we are looking up the user by email address, the HMAC is calculated using the email address value. If we were to look up the user by referral code, we would instead calculate the HMAC using the referral code value.

Generating the Signature

You can generate the HMAC  signature on your server (not client-side) using the following code, where USER-IDENTIFIER is either the email address, referral code, or id of the user.

Keep your secret key safe! Never commit it directly to your repository, client-side code, or anywhere a third party can find it.

Node.js

const crypto = require('crypto');

const signature = crypto
    .createHmac("sha256", "[PROJECT-SECRET]") // secret key (keep safe!)
    .update("[USER-IDENTIFIER]") // user's email, referral code, or id
    .digest("hex");

Ruby on Rails

require 'openssl'

OpenSSL::HMAC.hexdigest(
  'sha256', # hash function
  '[PROJECT-SECRET]', # secret key (keep safe!)
  '[USER-IDENTIFIER]' # user's email, referral code, or id
)

PHP

hash_hmac(
  'sha256', // hash function
  '[USER-IDENTIFIER]', // user's email, referral code, or id
  '[PROJECT-SECRET]' // secret key (keep safe!)
);

Django (Python 3)

import hmac
import hashlib

hmac.new(
  b'[PROJECT-SECRET]', # secret key (keep safe!)
  bytes('[USER-IDENTIFIER]', encoding='utf-8'), # user's email, referral code, or id
  digestmod=hashlib.sha256 # hash function
).hexdigest()

Troubleshooting

If you enable the Enforce Identity Verification feature, but do not sent a valid signature, then you will receive a HTTP 403 response.

Still need help? How can we help? How can we help?