Sample code for 30+ languages & platforms
React Native Requires Chilkat v11.0.0+

Verify Signature of Alexa Custom Skill Request

See more HTTP Misc Examples

This example verifies the signature of an Alexa Custom Skill Request.

Chilkat React Native Downloads

React Native
import { Cert, Http, Pem, PublicKey, Rsa, StringBuilder } from '@chilkat/react-native'

async function chilkatExample() {
  // This example assumes you have a web service that will receive requests from Alexa.
  // A sample request sent by Alexa will look like the following:

  // Connection: Keep-Alive
  // Content-Length: 2583
  // Content-Type: application/json; charset=utf-8
  // Accept: application/json
  // Accept-Charset: utf-8
  // Host: your.web.server.com
  // User-Agent: Apache-HttpClient/4.5.x (Java/1.8.0_172)
  // Signature: dSUmPwxc9...aKAf8mpEXg==
  // SignatureCertChainUrl: https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem
  // 
  // {"version":"1.0","session":{"new":true,"sessionId":"amzn1.echo-api.session.433 ... }}

  // First, assume we've written code to get the 3 pieces of data we need:
  const signature = 'dSUmPwxc9...aKAf8mpEXg==';
  const certChainUrl = 'https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem';
  const jsonBody = '{"version":"1.0","session":{"new":true,"sessionId":"amzn1.echo-api.session.433 ... }}';

  // To validate the signature, we do the following:

  // First, download the PEM-encoded X.509 certificate chain that Alexa used to sign the message 
  const http = new Http();
  const sbPem = new StringBuilder();
  try {
    await http.quickGetSbAsync(certChainUrl, sbPem);
  } catch {
    console.log(http.lastErrorText);
    return;
  }

  const pem = new Pem();
  try {
    pem.loadPem(sbPem.getAsString(), 'passwordNotUsed');
  } catch {
    console.log(pem.lastErrorText);
    return;
  }

  // The 1st certificate should be the signing certificate.
  let cert: Cert;
  try {
    cert = pem.getCert(0);
  } catch {
    console.log(pem.lastErrorText);
    return;
  }

  // Get the public key from the cert.
  const pubKey = new PublicKey();
  cert.getPublicKey(pubKey);

  // Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
  const rsa = new Rsa();
  try {
    rsa.usePublicKey(pubKey);
  } catch {
    console.log(cert.lastErrorText);
    return;
  }

  // RSA "decrypt" the signature.
  // (Amazon's documentation is confusing, because we're simply verifiying the signature against the SHA-1 hash
  // of the request body.  This happens in a single call to VerifyStringENC...)
  rsa.encodingMode = 'base64';
  try {
    rsa.verifyStringENC(jsonBody, 'sha1', signature);
    console.log('The signature is verified against the JSON body of the request. Yay!');
  } catch {
    console.log('Sorry, not verified.  Crud!');
  }
}