问题
I'm trying to publish an app on Shopify marketplace by following this documentation. And I'm stuck on step-3 of the oauth documentation wherein you have to do 'HMAC Signature Validation'.
Documentation states that you have to process the string (specified below) through HMAC-SHA256 using app's shared secret key.
String = "shop=some-shop.myshopify.com×tamp=1337178173"
I'm trying to implement the steps using Java. Following is gist of the code that I have used.
private static final String HMAC_ALGORITHM = "HmacSHA256";
String key = "hush";
String data = "shop=some-shop.myshopify.com×tamp=1337178173";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),HMAC_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
System.out.println(Hex.encodeHexString(rawHmac));
The code produces the following string:
c2812f39f84c32c2edaded339a1388abc9829babf351b684ab797f04cd94d4c7
Through some random search on Shopify developer forum I found the link to a question.
The last message from @Shayne suggests that we have to make changes in data
variable by adding protocol
field.
But it didn't work out :(
Can anyone tell me what should be done?Do I have to make modifications in my code or the process in the documentation have changed. Please help.
回答1:
The example is wrong apparently. Your hash code is OK. You'll need to make sure you include all parameters from the Shopify response e.g. the input for verification of a response would look like:
code={code}&protocol=https://&store={store}×tamp={timestamp}
See: https://ecommerce.shopify.com/c/shopify-apis-and-technology/t/you-broke-my-build-hmac-verification-broken-282951
回答2:
Here's the java code you need to verify Shopify HMAC. The protocol parameter isn't required unless it was in the result from shopify, which it wasn't from me.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String HMAC_ALGORITHM = "HmacSHA256";
resp.setContentType("text/html;charset=UTF-8");
Map<String,String[]> parameters = req.getParameterMap();
String data = null;
SortedSet<String> keys = new TreeSet<String>(parameters.keySet());
for (String key : keys) {
if (!key.equals("hmac")&&!key.equals("signature")){
if (data == null){
data = key + "=" +req.getParameter(key);
}
else {
data = data + "&" + key + "=" + req.getParameter(key);
}
}
}
SecretKeySpec keySpec = new SecretKeySpec(SHARED_KEY.getBytes(),HMAC_ALGORITHM);
Mac mac = null;
try {
mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(keySpec);
byte[] rawHmac = mac.doFinal(data.getBytes());
if (Hex.encodeHexString(rawHmac).equals(req.getParameter("hmac"))){
//THE HMAC IS VERIFIED
} else {
//THE HMAC IS NOT VERIFIED
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
}
Interestingly, the timestamp parameter in data turns into
×tamp=1459537704
instead of
×tamp=1459537704
回答3:
here is my prod code:
public class HMACValidator {
public static String sha256HMAC(String key, String data) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, DecoderException {
Mac hmac = Mac.getInstance("HmacSHA256");
System.out.println("data "+data);
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
hmac.init(secret_key);
return Hex.encodeHexString(hmac.doFinal(data.getBytes("UTF-8")));
}
public static boolean validateShopifyAskForPermission(String key, String hmac, String shop, String timestamp) throws Exception {
return (sha256HMAC(key, "shop="+shop+"×tamp="+timestamp).compareTo(hmac) == 0);
}
}
来源:https://stackoverflow.com/questions/32565052/hmac-sha256-issue-in-shopify-oauth-output-does-not-match