Skip to content

Instantly share code, notes, and snippets.

@tsjdev-apps
Created December 16, 2018 08:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsjdev-apps/128ba6213e041db01a9c7c4894202e7d to your computer and use it in GitHub Desktop.
Save tsjdev-apps/128ba6213e041db01a9c7c4894202e7d to your computer and use it in GitHub Desktop.
Validate an Alexa Request within Azure Functions.
using Alexa.NET.Request;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
namespace AlexaFunctionsApp
{
public static class SkillRequestExtension
{
public static async Task<bool> ValidateRequestAsync(this SkillRequest skillRequest, HttpRequest request, ILogger log)
{
// get signature certification chain url
var signatureCertChainUrl = GetSignatureCertChainUrlFromRequest(request);
if (signatureCertChainUrl == null)
{
log.LogError("Validation failed, because of incorrect SignatureCertChainUrl");
return false;
}
// get signature header
var signature = GetSignatureFromRequest(request);
if (string.IsNullOrWhiteSpace(signature))
{
log.LogError("Validation failed, because of empty signature");
return false;
}
// get body
var body = await GetBodyFromRequestAsync(request);
if (string.IsNullOrWhiteSpace(body))
{
log.LogError("Validation failed, because of empty body");
return false;
}
// validate timestamp
if (!IsTimestampValid(skillRequest))
{
log.LogError("Validation failed, because timestamp is not valid");
return false;
}
// validate signature, signaturecertchainurl and body
if (!await IsRequestValid(signature, signatureCertChainUrl, body))
{
log.LogError("Validation failed, because verification of request failed");
return false;
}
return true;
}
private static Uri GetSignatureCertChainUrlFromRequest(HttpRequest httpRequest)
{
httpRequest.Headers.TryGetValue("SignatureCertChainUrl", out var signatureCertChainUrlAsString);
if (string.IsNullOrWhiteSpace(signatureCertChainUrlAsString))
return null;
Uri signatureCertChainUrl;
try
{
signatureCertChainUrl = new Uri(signatureCertChainUrlAsString);
}
catch
{
return null;
}
return signatureCertChainUrl;
}
private static string GetSignatureFromRequest(HttpRequest httpRequest)
{
httpRequest.Headers.TryGetValue("Signature", out var signature);
return signature;
}
private static async Task<string> GetBodyFromRequestAsync(HttpRequest httpRequest)
{
httpRequest.Body.Position = 0;
var body = await httpRequest.ReadAsStringAsync();
httpRequest.Body.Position = 0;
return body;
}
private static bool IsTimestampValid(SkillRequest skillRequest)
{
return RequestVerification.RequestTimestampWithinTolerance(skillRequest);
}
private static async Task<bool> IsRequestValid(string signature, Uri signatureCertChainUrl, string body)
{
return await RequestVerification.Verify(signature, signatureCertChainUrl, body);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment