Shopify allows to embed pages into the admin site, to do that I can create a page using ASP.NET MVC and get the page shown in the admin panel of Shopify.
To validate if the page request is valid and was request by Shopify there are some parameters sent in the query string that the page has to validate before processing the request and render the page.
Shopify sends a hmac parameter so I can calculate the same parameter and validate if both are equal.
I was using Asp.Net Mvc 5 and used the AuthorizeAttribute class but now I am using Asp.Net Core and it seems authorization filters have changed.
I have read some articles about how is the new authorization system in Asp.Net Core but I can't determine what is the best way to do it.
So in the end I need:
Crete a custom attribute so I can add it to my controllers. When Shopify calls my pages I need to verify the query string parameters before the controller action starts to process the request, in the case the request is not valid the controller action is not called but if the request is valid it authorizes and lets the controller action to execute and render the page.
My current filter in Asp.Net MVC 5 is something like this:
namespace MyShopifyApp.Filters
{
public class EmbeddedAppAuthAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Validates if the nonce/state from the query string is correct
var stateParameter = httpContext.Request.QueryString["state"];
var nonce = ShopifyHelper.AuthorizationNonceManager.GetNonce(ProjectSettings.ShopifyShopUrl);
if (!string.IsNullOrEmpty(stateParameter))
{
if (string.IsNullOrEmpty(nonce) || stateParameter != nonce)
{
return false;
}
}
//Validates if the shop parameter from the query string is valid
var shopParameter = httpContext.Request.QueryString["shop"];
if (!ProjectSettings.IsValidShop(shopParameter))
return false;
//Calculates a HMAC signature and validates if the request is really from Shopify
if (!ShopifyAuthorizationService.IsAuthenticRequest(httpContext.Request.QueryString, ProjectSettings.ShopifyAdminAppApiSecret))
return false;
//Everything is correct so allow the request to continue
return true;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
}
}
}
This is an example controller:
namespace MyShopifyApp.Controllers
{
[EmbeddedAppAuth]
public class MyController : Controller
{
public async Task<ActionResult> Index(string hmac, string shop, string signature, string timeStamp, string protocol)
{
//Do something here only if the request is authentic and sent by Shopify
}
}
}