Skip to content

Commit c6d1094

Browse files
committed
Shopify header signature validation
1 parent aebe99d commit c6d1094

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/Umbraco.Cms.Integrations.OAuthProxy/Controllers/ShopifyComplianceController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using Microsoft.AspNetCore.Mvc;
2+
using Umbraco.Cms.Integrations.OAuthProxy.Filters;
23

34
namespace Umbraco.Cms.Integrations.OAuthProxy.Controllers
45
{
5-
[ApiController]
6+
[ApiController]
67
public class ShopifyComplianceController : Controller
78
{
89
/// <summary>
@@ -11,6 +12,7 @@ public class ShopifyComplianceController : Controller
1112
/// <returns></returns>
1213
[HttpPost]
1314
[Route("/shopify-compliance/v1/customer/data-request")]
15+
[SignatureValidation]
1416
public IActionResult CustomerDataRequest() => Ok();
1517

1618
/// <summary>
@@ -19,6 +21,7 @@ public class ShopifyComplianceController : Controller
1921
/// <returns></returns>
2022
[HttpPost]
2123
[Route("/shopify-compliance/v1/customer/data-redact")]
24+
[SignatureValidation]
2225
public IActionResult CustomerDataRedact() => Ok();
2326

2427
/// <summary>
@@ -27,6 +30,7 @@ public class ShopifyComplianceController : Controller
2730
/// <returns></returns>
2831
[HttpPost]
2932
[Route("/shopify-compliance/v1/shop/data-redact")]
33+
[SignatureValidation]
3034
public IActionResult ShopDataRedact() => Ok();
3135
}
3236
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.Mvc.Filters;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.Options;
5+
using System;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Security.Cryptography;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
using Umbraco.Cms.Integrations.OAuthProxy.Configuration;
12+
13+
namespace Umbraco.Cms.Integrations.OAuthProxy.Filters
14+
{
15+
public class SignatureValidationAttribute : ActionFilterAttribute
16+
{
17+
private const string HeaderKey = "X-Shopify-Hmac-Sha256";
18+
19+
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
20+
{
21+
var appSettings = context.HttpContext.RequestServices.GetService<IOptions<AppSettings>>().Value;
22+
23+
var hmacHeaderValues = context.HttpContext.Request.Headers
24+
.FirstOrDefault(kvp => kvp.Key.Equals(HeaderKey, StringComparison.OrdinalIgnoreCase)).Value;
25+
26+
if (hmacHeaderValues.Count == 0)
27+
{
28+
context.Result = new UnauthorizedResult();
29+
return;
30+
}
31+
32+
string hmacHeader = hmacHeaderValues.First();
33+
34+
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(appSettings.ShopifyClientSecret));
35+
36+
var bodyStream = new StreamReader(context.HttpContext.Request.Body);
37+
string requestBody = await bodyStream.ReadToEndAsync();
38+
string hash = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(requestBody)));
39+
40+
if (hash != hmacHeader)
41+
{
42+
context.Result = new UnauthorizedResult();
43+
return;
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)