Search code examples
azurepostmanalexa-skills-kit

Why a 400 response from Azure endpoint for Postman but works fine with the Alexa console?


I am new to developing Alexa skills so I am using a sample I found on the web as a C# endpoint hosted on Azure. It works correctly with the Alexa console but when I try to test the same endpoint with the Postman app, I get a 400 error.

When I use the Alexa console, it displays the JSON input that it sends to the endpoint and the JSON output that it receives from the endpoint. If I copy the JSON input and paste it into Postman and send it to the same endpoint, I get a 400 error. Obviously, I am missing something.

The following are my two source files and the JSON input.

RollTheDice.cs

public static class RollTheDice
{
    [FunctionName("RollTheDice")]
    public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
    {
    log.Info("C# HTTP trigger function processed a request.");

    var speechlet = new RollTheDiceSpeechlet();
    return await speechlet.GetResponseAsync(req);
    }
}

RollTheDiceSpeechlet.cs

public class RollTheDiceSpeechlet : SpeechletBase, ISpeechletWithContext
{
  public SpeechletResponse OnIntent(IntentRequest intentRequest, Session session, Context context)
  {
    try
    {
      // Default to 6 sides if not specified
      if (!int.TryParse(intentRequest.Intent.Slots["DiceType"].Value, out int numSides))
        numSides = 6;

      var rollResults = new Random().Next(Math.Max(1, numSides - 1)) + 1; // Account for random returning '0'
      return new SpeechletResponse
      {
        ShouldEndSession = false,
        OutputSpeech = new PlainTextOutputSpeech { Text = $"I rolled a {numSides} sided die and got a {rollResults}." }
      };
    }
    catch (Exception ex)
    {
      return new SpeechletResponse
      {
        ShouldEndSession = false,
        OutputSpeech = new PlainTextOutputSpeech { Text = ex.Message }
      };
    }

  }

  public SpeechletResponse OnLaunch(LaunchRequest launchRequest, Session session, Context context)
  {
    return new SpeechletResponse
    {
      ShouldEndSession = false,
      OutputSpeech = new PlainTextOutputSpeech { Text = "Welcome to the Roll the Dice. Ask me to roll the dice." }
    };
  }

  public void OnSessionEnded(SessionEndedRequest sessionEndedRequest, Session session, Context context)
  {
    return;
  }

  public void OnSessionStarted(SessionStartedRequest sessionStartedRequest, Session session, Context context)
  {
    return;
  }
}

JSON Input

Again, everything works fine but when I test it with Postman I get a 404 error. The endpoint is C# serverless function that I developed in Visual Studio 201. When I run it locally, I copy/paste the URL in the Postman app and send a post. See attached screenshots.

enter image description here enter image description here


Solution

  • As the error suggest you are missing Signature and SignatureCertChainUrl headers. These helps to protect your endpoint and verify that incoming requests were sent by Alexa. Any requests coming from other sources should be rejected. When you test it via Test Console these headers are included and you get successful response.

    Headers:

    Signature 
    SignatureCertChainUrl
    

    There are two parts to validating incoming requests:

    1. Check the request signature to verify the authenticity of the request.
    2. Check the request timestamp to ensure that the request is not an old request.

    More information on verifying that the request was sent by Alexa here