{"_id":"57756b0c260c8a0e00a98b33","project":"56abbf55f25f160d00e17f4e","__v":0,"user":"56abbec30b9e0b0d00616274","category":{"_id":"56af6d6ecc4cbd0d00ce2c88","pages":["56af6e8460a37a0d00ed87ac","56af71e58be2ea0d00b48887","56af73a08be2ea0d00b48890"],"version":"56abbf55f25f160d00e17f51","__v":3,"project":"56abbf55f25f160d00e17f4e","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-01T14:36:30.275Z","from_sync":false,"order":2,"slug":"concepts","title":"Kongregate APIs & Concepts"},"parentDoc":null,"version":{"_id":"56abbf55f25f160d00e17f51","project":"56abbf55f25f160d00e17f4e","__v":12,"createdAt":"2016-01-29T19:36:53.665Z","releaseDate":"2016-01-29T19:36:53.665Z","categories":["56abbf56f25f160d00e17f52","56abca6bf9757e0d007c6650","56acddfa0ab3c00d00ce3332","56af65da9d32e30d0006d30f","56af66cab34d210d003d9ad0","56af6afcd21e9c0d00b628d1","56af6d6ecc4cbd0d00ce2c88","5705b12221cfed0e00e8c580","570a5676ade45d0e00c1ad33","570d7d25d1e4b82000d9e385","570eac3c3160d10e0041df0e","575709000fd6a3200010dded"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-06-30T18:55:08.598Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":14,"body":"## Signed Requests/Callbacks\n\nKongregate now uses a **signed request** mechanism very similar to what [Facebook uses](https://developers.facebook.com/docs/authentication/signed_request/) 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.\n\n### Format\n\nJust like Facebook, the signed request is formatted as an [HMAC](http://en.wikipedia.org/wiki/HMAC) [SHA256](http://en.wikipedia.org/wiki/SHA-2) signature and a [base64url encoded](http://en.wikipedia.org/wiki/Base64#URL_applications) 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):\n\n```\nGbmlDg_VNvaFZFKMR6iIXBqQWtdCyzgwSPTc1IB7pC8\n.\neyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV2ZW50IjoidGVzdCJ9\n```\n\n### Decoding/Verifying\n\nThe 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](http://en.wikipedia.org/wiki/Base64#URL_applications) 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.\n\nHere is an example of how to decode a signed request in PHP, taken from Facebook's site:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"function parse_signed_request($signed_request, $secret) {\\n  list($encoded_sig, $payload) = explode('.', $signed_request, 2); \\n\\n  // decode the data\\n  $sig = base64_url_decode($encoded_sig);\\n  $data = json_decode(base64_url_decode($payload), true);\\n\\n  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {\\n    error_log('Unknown algorithm. Expected HMAC-SHA256');\\n    return null;\\n  }\\n\\n  // check sig\\n  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);\\n  if ($sig !== $expected_sig) {\\n    error_log('Bad Signed JSON signature!');\\n    return null;\\n  }\\n\\n  return $data;\\n}\\n\\nfunction base64_url_decode($input) {\\n  return base64_decode(strtr($input, '-_', '+/'));\\n}\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\n### Example\n\nLet's walk through decoding/verifying the above example step-by-step using the signed request and API key from above:\n\nAfter splitting the string, we have the signature `GbmlDg_VNvaFZFKMR6iIXBqQWtdCyzgwSPTc1IB7pC8` and the payload `eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV2ZW50IjoidGVzdCJ9`\n\nWe 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\"}`\n\nIn 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.\n\n### Additional Resources\n\n*   [Ruby base64_url decode](http://qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-for-signed_request/)\n*   [Ruby HMAC SHA256 example (arguments are reversed compared to PHP)](http://stackoverflow.com/questions/1336909/ruby-and-php-hmacs-not-agreeing)","excerpt":"","slug":"concepts-signed-requests","type":"basic","title":"Signed Requests"}
## Signed Requests/Callbacks Kongregate now uses a **signed request** mechanism very similar to what [Facebook uses](https://developers.facebook.com/docs/authentication/signed_request/) 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](http://en.wikipedia.org/wiki/HMAC) [SHA256](http://en.wikipedia.org/wiki/SHA-2) signature and a [base64url encoded](http://en.wikipedia.org/wiki/Base64#URL_applications) 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](http://en.wikipedia.org/wiki/Base64#URL_applications) 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: [block:code] { "codes": [ { "code": "function parse_signed_request($signed_request, $secret) {\n list($encoded_sig, $payload) = explode('.', $signed_request, 2); \n\n // decode the data\n $sig = base64_url_decode($encoded_sig);\n $data = json_decode(base64_url_decode($payload), true);\n\n if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {\n error_log('Unknown algorithm. Expected HMAC-SHA256');\n return null;\n }\n\n // check sig\n $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);\n if ($sig !== $expected_sig) {\n error_log('Bad Signed JSON signature!');\n return null;\n }\n\n return $data;\n}\n\nfunction base64_url_decode($input) {\n return base64_decode(strtr($input, '-_', '+/'));\n}", "language": "php" } ] } [/block] ### 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 * [Ruby base64_url decode](http://qugstart.com/blog/ruby-and-rails/facebook-base64-url-decode-for-signed_request/) * [Ruby HMAC SHA256 example (arguments are reversed compared to PHP)](http://stackoverflow.com/questions/1336909/ruby-and-php-hmacs-not-agreeing)