Signed Requests

Signed Requests/Callbacks

Kongregate now uses a signed request mechanism for our API callbacks. This makes it easy to verify that a given callback request is indeed coming from Kongregate. When you receive a signed request from Kongregate you must decode and verify it before using the parameters inside.

Format

Just like Facebook, the signed request is formatted as an HMAC SHA256 signature and a base64url encoded JSON payload, joined with a period. Here is an example of a signed request for a game which has a secret API key of 748e63d7-c48c-418c-aa25-80456de2b98c (newlines added for readability):

GbmlDg_VNvaFZFKMR6iIXBqQWtdCyzgwSPTc1IB7pC8
.
eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV2ZW50IjoidGVzdCJ9

Decoding/Verifying

The signed request will be transmitted as a POST variable named signed_request. In order to decode and verify the signed request, you should first split the string at the period. The first part is the signature, and the second part is the base64-encoded JSON payload. You should base64url decode and JSON parse the payload, and then verify the algorithm element of the object is a string equal to HMAC-SHA256. Next, calculate the HMAC signature of the base64-encoded payload using your game's API key, and ensure that it matches the provided signature.

Here is an example of how to decode a signed request in PHP, taken from Facebook's site:

function parse_signed_request($signed_request, $secret) {
  list($encoded_sig, $payload) = explode('.', $signed_request, 2); 

  // decode the data
  $sig = base64_url_decode($encoded_sig);
  $data = json_decode(base64_url_decode($payload), true);

  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    error_log('Unknown algorithm. Expected HMAC-SHA256');
    return null;
  }

  // check sig
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
  }

  return $data;
}

function base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

Example

Let's walk through decoding/verifying the above example step-by-step using the signed request and API key from above:

After splitting the string, we have the signature GbmlDg_VNvaFZFKMR6iIXBqQWtdCyzgwSPTc1IB7pC8 and the payload eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV2ZW50IjoidGVzdCJ9

We base64-decode and parse the payload to get the JSON object. You can see that the algorithm is indeed HMAC-SHA256: {"algorithm":"HMAC-SHA256","event":"test"}

In order to verify the signature, we calculate the HMAC-SHA256 signature with the API key and ensure that it is equal to the provided signature. If it matches, then we are sure this request came from Kongregate's servers, and it is safe to proceed. If not, the request should simply be logged or ignored.

Additional Resources