Advertisement
Guest User

Amazon Alexa Validation

a guest
Aug 17th, 2015
3,083
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.45 KB | None | 0 0
  1. //
  2. // Validate keychainUri is proper (from Amazon)
  3. //
  4. function validateKeychainUri($keychainUri){
  5.  
  6.     $uriParts = parse_url($keychainUri);
  7.  
  8.     if (strcasecmp($uriParts['host'], 's3.amazonaws.com') != 0)
  9.         fail('The host for the Certificate provided in the header is invalid');
  10.  
  11.     if (strpos($uriParts['path'], '/echo.api/') !== 0)
  12.         fail('The URL path for the Certificate provided in the header is invalid');
  13.  
  14.     if (strcasecmp($uriParts['scheme'], 'https') != 0)
  15.         fail('The URL is using an unsupported scheme. Should be https');
  16.  
  17.     if (array_key_exists('port', $uriParts) && $uriParts['port'] != '443')
  18.         fail('The URL is using an unsupported https port');
  19.  
  20. }
  21.  
  22. //
  23. // Fail - die() replacement with error logging
  24. //
  25. function fail($message) {
  26.  
  27.     error_log($message);
  28.     die();
  29.  
  30. }
  31.  
  32. $applicationIdValidation    = 'amzn1.echo-sdk-ams.app.GUID####';
  33. $userIdValidation           = 'amzn1.account.GUID###';
  34. $echoServiceDomain          = 'echo-api.amazon.com';
  35.  
  36. // Capture Amazon's POST JSON request:
  37. $jsonRequest    = file_get_contents('php://input');
  38. $data           = json_decode($jsonRequest, true);
  39.  
  40. //
  41. // Parse out key variables
  42. //
  43. $sessionId          = @$data['session']['sessionId'];
  44. $applicationId      = @$data['session']['application']['applicationId'];
  45. $userId             = @$data['session']['user']['userId'];
  46. $requestTimestamp   = @$data['request']['timestamp'];
  47. $requestType        = $data['request']['type'];
  48.  
  49. // Die if applicationId isn't valid
  50. if ($applicationId != $applicationIdValidation) fail('Invalid Application id: ' . $applicationId);
  51.  
  52. // Die if this request isn't coming from Matt Farley's Amazon Account
  53. if ($userId != $userIdValidation) fail('Invalid User id: ' . $userId);
  54.  
  55. // Determine if we need to download a new Signature Certificate Chain from Amazon
  56. $md5pem = md5($_SERVER['HTTP_SIGNATURECERTCHAINURL']);
  57. $md5pem = $md5pem . '.pem';
  58.  
  59. // If we haven't received a certificate with this URL before, store it as a cached copy
  60. if (!file_exists($md5pem)) {
  61.     file_put_contents($md5pem, file_get_contents($_SERVER['HTTP_SIGNATURECERTCHAINURL']));
  62. }
  63.  
  64. // Validate proper format of Amazon provided certificate chain url
  65. validateKeychainUri($_SERVER['HTTP_SIGNATURECERTCHAINURL']);
  66.  
  67. // Validate certificate chain and signature
  68. $pem = file_get_contents($md5pem);
  69. $ssl_check = openssl_verify($jsonRequest, base64_decode($_SERVER['HTTP_SIGNATURE']), $pem);
  70. if ($ssl_check != 1)
  71.     fail(openssl_error_string());
  72.  
  73. // Parse certificate for validations below
  74. $parsedCertificate = openssl_x509_parse($pem);
  75. if (!$parsedCertificate)
  76.     fail('x509 parsing failed');
  77.  
  78. // Check that the domain echo-api.amazon.com is present in the Subject Alternative Names (SANs) section of the signing certificate
  79. if(strpos($parsedCertificate['extensions']['subjectAltName'], $echoServiceDomain) === false)
  80.     fail('subjectAltName Check Failed');
  81.  
  82. // Check that the signing certificate has not expired (examine both the Not Before and Not After dates)
  83. $validFrom = $parsedCertificate['validFrom_time_t'];
  84. $validTo   = $parsedCertificate['validTo_time_t'];
  85. $time      = time();
  86. if (!($validFrom <= $time && $time <= $validTo))
  87.     fail('certificate expiration check failed');
  88.  
  89. // Check the timestamp of the request and ensure it was within the past minute
  90. if (time() - strtotime($requestTimestamp) > 60)
  91.     fail('timestamp validation failure.. Current time: ' . time() . ' vs. Timestamp: ' . $requestTimestamp);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement