hmac validation fails for webhooks with credit card info

GeorgeHoffman
Shopify Partner
19 0 3

I am trying to verify hmac for order created webhooks in java springboot application. The validation works for webhooks without credit card information (free due to discounts). For orders with credit card info its coming through with some special characters and hmac validation fails. Below is the relevant code: 

	@PostMapping("/order-create")
	public String orderCreatedWebhook(HttpServletRequest req, HttpServletResponse resp,HttpSession ses, @RequestBody String body){
	        Mac mac = Mac.getInstance("HmacSHA256");
	        mac.init(new SecretKeySpec(secret.getBytes(), HMAC_SHA_256));			
	        byte[] bytes = mac.doFinal(body.getBytes(UTF_8));
	        boolean valid = req.getHeader("X-Shopify-Hmac-SHA256").equals(Base64.encodeBase64String(bytes));	        

 What do I need to do to validate this request. I believe springboot uses UTF-8 by default. Does shopify use some other encoding?

Reply 1 (1)
GeorgeHoffman
Shopify Partner
19 0 3
zuul gateway changes the character encoding to some ISO format ... This seems to fix the issue: final String body = IOUtils.toString(req.getInputStream(),"UTF-8");
 
Posting so others dont need to go through the same pain as me last few days. If you use a spring boot app with or without zuul gateway the below should work for you. IOUtils comes from apache commons. 

 

 

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.IOUtils;

@PostMapping("/order-create")
	public String orderCreatedWebhook(HttpServletRequest req, HttpServletResponse resp,HttpSession ses){
	        final String body = IOUtils.toString(req.getInputStream(),"UTF-8");
	        Mac mac = Mac.getInstance("HmacSHA256");
	        mac.init(new SecretKeySpec("mywebhooksecretfromnotificationsettings".getBytes(),"HmacSHA256"));			
	        byte[] bytes = mac.doFinal(body.getBytes(UTF_8));
	        boolean valid = req.getHeader("X-Shopify-Hmac-SHA256").equals(Base64.encodeBase64String(bytes));