ShopifySharp icon indicating copy to clipboard operation
ShopifySharp copied to clipboard

Validates web requests fails for bulk admin actions

Open arsuceno opened this issue 5 years ago • 1 comments

Shopify admin has the option to add bulk action links in orders/products/customers... pages. For these cases the request query string looks like this:

hmac=XXXXXX&ids%5B%5D=2074861961283&ids%5B%5D=2074861830211&locale=en&shop=YYYYYYYYYYY&timestamp=1552479578

These requests are not well documented in Shopify documentation, but as it is explained here https://community.shopify.com/c/Shopify-APIs-SDKs/Hmac-weirdness-when-working-with-Shop-admin-links-gt-Products/m-p/293628#M14200 , the query string used for hmac calculation looks like this

ids=["2074861961283", "2074861830211"]&locale=en&shop=YYYYYYYYYYY&timestamp=1552479578

Adding this code at the beggining of PrepareQueryString within AuthorizationService.cs fix the validation for these cases:

        private static string PrepareQuerystring(IEnumerable<KeyValuePair<string, StringValues>> querystring, string joinWith)
        {
            if (string.IsNullOrEmpty(querystring.FirstOrDefault(kvp => kvp.Key == "ids").Value))
            {
                var ids = string.Join(", ", querystring.FirstOrDefault(kvp => kvp.Key == "ids[]").Value.Select(id => $"\"{id}\""));
                querystring = querystring.Concat(new[] { new KeyValuePair<string, StringValues>("ids", $"[{ids}]") });
                querystring = querystring.Where(x => x.Key != "ids[]");
            }

            var kvps = querystring.Select(kvp => new
            ....

I want to make a PR to handle this case, but I don't have the API key used in tests to create similar ones. I could create it anyway but then someone should fix it:

        [Fact]
        public void Validates_Web_Bulk_Links_Requests()
        {
            // hmac=XXX&ids[]=2065145364547&ids[]=2065146314819&locale=en&shop=YYY&timestamp=1551874047
            var qs = new Dictionary<string, StringValues>()
            {
                {"hmac", "XXX"},
                {"ids[]", new StringValues(new[] {"2065145364547", "2065146314819" }) },
                {"locale", "en"},
                {"shop", "YYY"},
                {"timestamp", "1551874047"},
            };

            bool isValid = AuthorizationService.IsAuthenticRequest(qs, Utils.SecretKey);

            Assert.True(isValid);
        }

arsuceno avatar Mar 13 '19 12:03 arsuceno

Thanks for the report! I'm actually a bit surprised that this isn't working for you, I'm pretty sure it's working for my own apps with admin actions. I'll try to get a unit test for this using the correct API key.

nozzlegear avatar Mar 14 '19 18:03 nozzlegear