I'm using Play framework to develop consumer for Instagram real-time API. But still could not perform x-hub-signature verification properly. So, how can we perform Instagram x-hub-signature verification using Java and Play framework?
Here is my current code:
From the Play framework, I obtain the JSON payload using this method:
public static Result receiveInstaData(){ JsonNode json = request().body().asJson(); //obtain the x-hub-signature from the header //obtain the corresponding client secret VerificationResult verificationResult = SubscriptionUtil.verifySubscriptionPostSignature( clientSecret, json.toString(), xHubSignature); if(verificationResult.isSuccess()){ //do something } }
Then inside the
SubscriptionUtil
, I perform verification using this following code:public static VerificationResult verifySubscriptionPostSignature(String clientSecret, String rawJsonData, String xHubSignature) { SecretKeySpec keySpec; keySpec = new SecretKeySpec(clientSecret.getBytes("UTF-8"), HMAC_SHA1); Mac mac; mac = Mac.getInstance(HMAC_SHA1); mac.init(keySpec); byte[] result; result = mac.doFinal(rawJsonData.getBytes("UTF-8")); String encodedResult = Hex.encodeHexString(result); return new VerificationResult(encodedResult.equals(xHubSignature), encodedResult); }
I created a standalone Python script that copies the instagram-python implementation and both of them produce the same results for the same clientSecret
and jsonString
. Maybe I should provide with raw binary data instead of String.
If let's say we need a raw binary data for JSON request, then I need to create my custom BodyParser to parse the JSON request to raw binary data[5]
References:
[1-4]http://pastebin.com/g4uuDwzn (SO doesn't allow me to post more than 2 links, so I put all the references here. The links contain the signature verification in Ruby, Python and PHP)
[5]https://groups.google.com/forum/#!msg/play-framework/YMQb6yeDH5o/jU8FD--yVPYJ
[6]My standalone python script: #! /usr/bin/env python
import sys
import hmac
import hashlib
hc_client_secret = "myclientsecret"
hc_raw_response = "[{\"subscription_id\":\"1\",\"object\":\"user\",\"object_id\":\"1234\",\"changed_aspect\":\"media\",\"time\":1297286541},{\"subscription_id\":\"2\",\"object\":\"tag\",\"object_id\":\"nofilter\",\"changed_aspect\":\"media\",\"time\":1297286541}]"
client_secret = hc_client_secret
raw_response = hc_raw_response
if len(sys.argv) != 3:
print 'Usage verify_signature <client_secret> <raw_response>.\nSince the inputs are invalid, use the hardcoded value instead!'
else:
client_secret = sys.argv[1]
raw_response = sys.argv[2]
print "client_secret = " + client_secret
print "raw_response = " + raw_response
digest = hmac.new(client_secret.encode('utf-8'), msg=raw_response.encode('utf-8'), digestmod=hashlib.sha1).hexdigest()
print digest