Proxy signature mismatch

Solved
Highlighted
Tourist
4 0 1

Hello everyone,

 

this will be my first post on this forums and I have an issue. I followed the official shopify guide on creating a proxy route and authenticating the incoming traffic on my nodejs server using koa. I have linked the guide that I followed below. The issue that I'm facing is that the calculated hash and the signature do not match. Hopefully someone will be able to help me out with this. Thank you all in advance.

Additional information:
- I have triple checked that I'm using the correct API keys.
- I'm testing the connection using a simple ajax request.
- I am receiving the request and the entire query content, but the hash and signature don't match.

- Guide: https://shopify.dev/tutorials/display-data-on-an-online-store-with-an-application-proxy-app-extensio...

NodeJS route:

 

router.get('*', async (ctx, next) => {
    let query_string = ctx.querystring;
    console.log(`query-string: ${query_string}`);

    let query_hash = ctx.request.query;
    console.log(query_hash);

    let signature = query_hash.signature;
    console.log(`signature: ${signature}`);

    delete query_hash.signature;

    let sorted_params = convert(query_hash);
    console.log(`sorted_params: ${sorted_params}`);

    let hash = crypto.createHash('sha256', SHARED_SECRET).update(sorted_params).digest('hex');

    console.log(`hash: ${hash}`);
    console.log(`signatury: ${signature}`);
    // next();
});

Ajax request:

  $.ajax({
    url: '/apps/data/orders/save',
    type: 'GET'
  });
0 Likes
Highlighted
Shopify Staff
Shopify Staff
1041 140 167

Hey @Skennem 

 

Are you able to share the convert function code / can you confirm it's sorting correctly?

Notice; Out of office, replies will be delayed until my return. Thanks!
0 Likes
Highlighted
Tourist
4 0 1

Yes I can confirm the sorting is correctly done. I have shared the convert function below. And I have also included some debug print statements that were printed on a get request without any additional parameters. 

function convert (object) {
    let sort = Object.entries(object).sort();
    let output = "";

    for (let [k, v] of sort) {
        output += `${k}=${v}`;
    }

    return output;
}

 

query-string: shop=skennem-development.myshopify.com&path_prefix=%2Fapps%2Fdata&timestamp=1591274805&signature=3a
816b72761a23a9910ec63dce745daa0dbdef07552681dcf693d5f31dce2011
sorted_params: path_prefix=/apps/datashop=skennem-development.myshopify.comtimestamp=1591274805
hash: f4f2f27dffc4dca888bb942991d05a0a55feb98354fadb667ca0e4b48fe28adc
signature: 3a816b72761a23a9910ec63dce745daa0dbdef07552681dcf693d5f31dce2011 

 

0 Likes
Highlighted
Shopify Staff
Shopify Staff
1041 140 167

This is an accepted solution.

Ah, you'll want createHmac instead of createHash:

 

const crypto = require('crypto')
const SHARED_SECRET = 'hush'
const sorted_params = "extra=1,2path_prefix=/apps/awesome_reviewsshop=shop-name.myshopify.comtimestamp=1317327555"
crypto.createHmac('sha256', SHARED_SECRET).update(sorted_params).digest('hex')
=> d37fb643f212c005d6bf7181e2e70fcee29c22b7c391cb4c6f0bfee482447c40


Compared to the ruby example:

require 'openssl'
SHARED_SECRET = 'hush'
sorted_params = "extra=1,2path_prefix=/apps/awesome_reviewsshop=shop-name.myshopify.comtimestamp=1317327555"
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), SHARED_SECRET, sorted_params)
=> d37fb643f212c005d6bf7181e2e70fcee29c22b7c391cb4c6f0bfee482447c40

 

Notice; Out of office, replies will be delayed until my return. Thanks!
0 Likes
Highlighted
Tourist
4 0 1

Thank you so much. I knew it had to be something stupid like that.

1 Like