From a8ab85977ca84c692fae4f6822422adab0a26072 Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 27 May 2021 07:40:20 -0400 Subject: [PATCH] broken out NotificationParser to decouple from required use of HttpListenerRequest --- .../Notifications/NotificationHandler.cs | 4 ++-- .../Notifications/NotificationParser.cs | 24 +++++++++++++++++++ Riskified.SDK/Orders/OrdersGateway.cs | 1 - Riskified.SDK/Utils/HttpUtils.cs | 21 ++++++++++++---- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 Riskified.SDK/Notifications/NotificationParser.cs diff --git a/Riskified.SDK/Notifications/NotificationHandler.cs b/Riskified.SDK/Notifications/NotificationHandler.cs index 767c0d7..54d4157 100644 --- a/Riskified.SDK/Notifications/NotificationHandler.cs +++ b/Riskified.SDK/Notifications/NotificationHandler.cs @@ -94,8 +94,8 @@ public void ReceiveNotifications() bool acionSucceeded = false; try { - var notificationData = HttpUtils.ParsePostRequestToObject>(request,_authToken); - OrderNotification n = new OrderNotification(notificationData); + OrderNotification n = NotificationParser.ParseListenerRequest(request, _authToken); + responseString = string.Format( "Merchant Received Notification For Order {0} with status {1} and description {2}", diff --git a/Riskified.SDK/Notifications/NotificationParser.cs b/Riskified.SDK/Notifications/NotificationParser.cs new file mode 100644 index 0000000..e23e64f --- /dev/null +++ b/Riskified.SDK/Notifications/NotificationParser.cs @@ -0,0 +1,24 @@ +using System.Net; +using Riskified.SDK.Model; +using Riskified.SDK.Model.Internal; +using Riskified.SDK.Utils; + +namespace Riskified.SDK.Notifications +{ + public static class NotificationParser + { + public static string HmacHeaderName => HttpUtils.HmacHeaderName; + + public static OrderNotification ParseListenerRequest(HttpListenerRequest request, string authToken) + { + var notificationData = HttpUtils.ParsePostRequestToObject>(request, authToken); + return new OrderNotification(notificationData); + } + + public static OrderNotification ParseRequestComponents(string hmacHeader, string requestBody, string authToken) + { + var notificationData = HttpUtils.ParsePostRequestComponentsToObject>(hmacHeader, requestBody, authToken); + return new OrderNotification(notificationData); + } + } +} \ No newline at end of file diff --git a/Riskified.SDK/Orders/OrdersGateway.cs b/Riskified.SDK/Orders/OrdersGateway.cs index b505d6d..583d895 100644 --- a/Riskified.SDK/Orders/OrdersGateway.cs +++ b/Riskified.SDK/Orders/OrdersGateway.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Riskified.SDK.Exceptions; using Riskified.SDK.Model; using Riskified.SDK.Utils; diff --git a/Riskified.SDK/Utils/HttpUtils.cs b/Riskified.SDK/Utils/HttpUtils.cs index e0dc392..1308b32 100644 --- a/Riskified.SDK/Utils/HttpUtils.cs +++ b/Riskified.SDK/Utils/HttpUtils.cs @@ -20,7 +20,7 @@ internal enum HttpBodyType internal static class HttpUtils { private const string ShopDomainHeaderName = "X-RISKIFIED-SHOP-DOMAIN"; - private const string HmacHeaderName = "X-RISKIFIED-HMAC-SHA256"; + internal const string HmacHeaderName = "X-RISKIFIED-HMAC-SHA256"; private const int ServerApiVersion = 2; private static readonly string AssemblyVersion; @@ -233,7 +233,7 @@ internal class ErrorMessage /// An object of type T containing data parsed from the request /// On missing/bad HMAC signature that doesn't match the given auth token /// On parsing error from string into the relevant object of type T - public static T ParsePostRequestToObject(HttpListenerRequest request,string authToken) where T : class + internal static T ParsePostRequestToObject(HttpListenerRequest request,string authToken) where T : class { if (!request.HasEntityBody) { @@ -243,14 +243,23 @@ public static T ParsePostRequestToObject(HttpListenerRequest request,string a T obj = JsonStringToObject(postData); return obj; } + + internal static T ParsePostRequestComponentsToObject(string hmacHeader, string requestBody, string authToken) where T : class + { + if (!AuthorizeContent(hmacHeader, requestBody, authToken)) + { + throw new RiskifiedAuthenticationException("Request HMAC signature was either missing or incorrect"); + } + return JsonStringToObject(requestBody); + } private static string AuthorizeAndExtractContent(HttpListenerRequest request, string authToken) { if (!string.IsNullOrEmpty(request.Headers[HmacHeaderName])) { - Stream s = request.InputStream; - string postData = ExtractStreamData(s); - if (string.Equals(request.Headers[HmacHeaderName], CalcHmac(postData, authToken), StringComparison.Ordinal)) + var s = request.InputStream; + var postData = ExtractStreamData(s); + if (AuthorizeContent(request.Headers[HmacHeaderName], postData, authToken)) { return postData; } @@ -258,6 +267,8 @@ private static string AuthorizeAndExtractContent(HttpListenerRequest request, st throw new RiskifiedAuthenticationException("Request HMAC signature was either missing or incorrect"); } + private static bool AuthorizeContent(string expectedSignature, string postData, string authToken) => string.Equals(expectedSignature, CalcHmac(postData, authToken), StringComparison.Ordinal); + private static string ExtractStreamData(Stream stream) { if (stream != null)