Sample code for 30+ languages & platforms
SQL Server

Verify Signature of Alexa Custom Skill Request

See more HTTP Misc Examples

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

Chilkat SQL Server Downloads

SQL Server
-- Important: See this note about string length limitations for strings returned by sp_OAMethod calls.
--
CREATE PROCEDURE ChilkatSample
AS
BEGIN
    DECLARE @hr int
    DECLARE @iTmp0 int
    -- Important: Do not use nvarchar(max).  See the warning about using nvarchar(max).
    DECLARE @sTmp0 nvarchar(4000)
    DECLARE @success int
    SELECT @success = 0

    -- 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:
    DECLARE @signature nvarchar(4000)
    SELECT @signature = 'dSUmPwxc9...aKAf8mpEXg=='
    DECLARE @certChainUrl nvarchar(4000)
    SELECT @certChainUrl = 'https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem'
    DECLARE @jsonBody nvarchar(4000)
    SELECT @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 
    DECLARE @http int
    EXEC @hr = sp_OACreate 'Chilkat.Http', @http OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END

    DECLARE @sbPem int
    EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbPem OUT

    EXEC sp_OAMethod @http, 'QuickGetSb', @success OUT, @certChainUrl, @sbPem
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        RETURN
      END

    DECLARE @pem int
    EXEC @hr = sp_OACreate 'Chilkat.Pem', @pem OUT

    EXEC sp_OAMethod @sbPem, 'GetAsString', @sTmp0 OUT
    EXEC sp_OAMethod @pem, 'LoadPem', @success OUT, @sTmp0, 'passwordNotUsed'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pem, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        RETURN
      END

    -- The 1st certificate should be the signing certificate.
    DECLARE @cert int
    EXEC sp_OAMethod @pem, 'GetCert', @cert OUT, 0
    EXEC sp_OAGetProperty @pem, 'LastMethodSuccess', @iTmp0 OUT
    IF @iTmp0 = 0
      BEGIN
        EXEC sp_OAGetProperty @pem, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        RETURN
      END

    -- Get the public key from the cert.
    DECLARE @pubKey int
    EXEC @hr = sp_OACreate 'Chilkat.PublicKey', @pubKey OUT

    EXEC sp_OAMethod @cert, 'GetPublicKey', @success OUT, @pubKey

    EXEC @hr = sp_OADestroy @cert

    -- Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
    DECLARE @rsa int
    EXEC @hr = sp_OACreate 'Chilkat.Rsa', @rsa OUT

    EXEC sp_OAMethod @rsa, 'UsePublicKey', @success OUT, @pubKey
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @cert, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        EXEC @hr = sp_OADestroy @pubKey
        EXEC @hr = sp_OADestroy @rsa
        RETURN
      END

    -- 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...)
    EXEC sp_OASetProperty @rsa, 'EncodingMode', 'base64'
    DECLARE @bVerified int
    EXEC sp_OAMethod @rsa, 'VerifyStringENC', @bVerified OUT, @jsonBody, 'sha1', @signature
    IF @bVerified = 1
      BEGIN

        PRINT 'The signature is verified against the JSON body of the request. Yay!'
      END
    ELSE
      BEGIN

        PRINT 'Sorry, not verified.  Crud!'
      END

    EXEC @hr = sp_OADestroy @http
    EXEC @hr = sp_OADestroy @sbPem
    EXEC @hr = sp_OADestroy @pem
    EXEC @hr = sp_OADestroy @pubKey
    EXEC @hr = sp_OADestroy @rsa


END
GO