From 78d84bfc0f8b721d6eddb8c2aae42eb9310e43ef Mon Sep 17 00:00:00 2001 From: Bran Date: Wed, 8 Apr 2020 03:06:16 +0200 Subject: [PATCH 1/3] - Alexa.NET package updated to version 1.13.0 - Added a cache for the certificate to reduce the time required for request verification. --- .../Alexa.NET.Security.Functions.csproj | 2 +- ...lexaRequestValidationFunctionsExtension.cs | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Alexa.NET.Security.Functions/Alexa.NET.Security.Functions.csproj b/Alexa.NET.Security.Functions/Alexa.NET.Security.Functions.csproj index cf5989d..a9106dc 100644 --- a/Alexa.NET.Security.Functions/Alexa.NET.Security.Functions.csproj +++ b/Alexa.NET.Security.Functions/Alexa.NET.Security.Functions.csproj @@ -22,7 +22,7 @@ - + diff --git a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs index f407781..5646de5 100644 --- a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs +++ b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs @@ -3,12 +3,16 @@ using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Extensions.Logging; using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; namespace Alexa.NET.Security.Functions { public static class AlexaRequestValidationFunctionsExtension { + private static KeyValuePair certificateCache; + /// /// Validates an incoming request against Amazon security guidelines. /// @@ -83,6 +87,24 @@ private static Uri GetSignatureCertChainUrlFromRequest(HttpRequest httpRequest) return signatureCertChainUrl; } + private static async Task GetCertificate(Uri signatureCertChainUrl) + { + if (certificateCache.Key == null || certificateCache.Key.ToString() != signatureCertChainUrl.ToString()) + { + X509Certificate2 certificate = await RequestVerification.GetCertificate(signatureCertChainUrl); + if (certificate != null) + { + certificateCache = new KeyValuePair(signatureCertChainUrl, certificate); + } + + return certificate; + } + else + { + return certificateCache.Value; + } + } + /// /// Gets the Signature value from http request headers. /// @@ -124,7 +146,7 @@ private static bool IsTimestampValid(SkillRequest skillRequest) /// private static async Task IsRequestValid(string signature, Uri signatureCertChainUrl, string body) { - return await RequestVerification.Verify(signature, signatureCertChainUrl, body); + return await RequestVerification.Verify(signature, signatureCertChainUrl, body, GetCertificate); } } } \ No newline at end of file From 8c63a1f7eadf7a3707f25119585d6a09d56e3bb6 Mon Sep 17 00:00:00 2001 From: Bran Date: Wed, 8 Apr 2020 11:28:21 +0200 Subject: [PATCH 2/3] - Validate uri is not null - Use the same code style of the rest of the file --- .../AlexaRequestValidationFunctionsExtension.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs index 5646de5..951a14d 100644 --- a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs +++ b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs @@ -89,20 +89,19 @@ private static Uri GetSignatureCertChainUrlFromRequest(HttpRequest httpRequest) private static async Task GetCertificate(Uri signatureCertChainUrl) { + if(signatureCertChainUrl == null) + return null; + if (certificateCache.Key == null || certificateCache.Key.ToString() != signatureCertChainUrl.ToString()) { X509Certificate2 certificate = await RequestVerification.GetCertificate(signatureCertChainUrl); if (certificate != null) - { certificateCache = new KeyValuePair(signatureCertChainUrl, certificate); - } return certificate; } - else - { + else return certificateCache.Value; - } } /// From 62ae02c782d7709d01af0ed4f2cefae67f16207e Mon Sep 17 00:00:00 2001 From: Bran Date: Wed, 8 Apr 2020 11:44:57 +0200 Subject: [PATCH 3/3] - Case insensitive comparing --- ...lexaRequestValidationFunctionsExtension.cs | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs index 951a14d..27a9aa6 100644 --- a/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs +++ b/Alexa.NET.Security.Functions/AlexaRequestValidationFunctionsExtension.cs @@ -89,18 +89,25 @@ private static Uri GetSignatureCertChainUrlFromRequest(HttpRequest httpRequest) private static async Task GetCertificate(Uri signatureCertChainUrl) { - if(signatureCertChainUrl == null) + if (signatureCertChainUrl == null) return null; - if (certificateCache.Key == null || certificateCache.Key.ToString() != signatureCertChainUrl.ToString()) + if (certificateCache.Key == null || certificateCache.Key.ToString().ToLowerInvariant() != signatureCertChainUrl.ToString().ToLowerInvariant()) { - X509Certificate2 certificate = await RequestVerification.GetCertificate(signatureCertChainUrl); - if (certificate != null) - certificateCache = new KeyValuePair(signatureCertChainUrl, certificate); - - return certificate; + try + { + X509Certificate2 certificate = await RequestVerification.GetCertificate(signatureCertChainUrl); + if (certificate != null) + certificateCache = new KeyValuePair(signatureCertChainUrl, certificate); + + return certificate; + } + catch + { + return null; + } } - else + else return certificateCache.Value; }