26 september, 2011

Verify Facebook Signed Request in Java


I'm writing this post after some frustration using Facebook's Registration social plugin. The plugin is great, no issues at all, the problem is in the verification of the 'signed_request'-query parameter in the response from Facebook. The documentation is not very clarifying and the only code-example is in PHP and there are som differences.

Some pointers:
  • The signed_request is encoded using Base64Url-encoding, not plain Base64-encoding.
  • The signed_request contains two parts (divided by a '.'), the first is the signature and the other is the JSON-payload.
  • The signature must be verified
The Java-code to verify the signature looks like this

public static boolean verifySignedRequest(String signedRequest, String appSecret){
        try {
            String[] split = signedRequest.split("\\.");

            Base64 base64 = new Base64(true); // URL-mode
            String encodedSignature = split[0];
            String encodedPayload = split[1];

            String SIGN_ALGORITHM = "HMACSHA256";
            Mac mac = Mac.getInstance(SIGN_ALGORITHM);
            SecretKeySpec secretKeySpec = new SecretKeySpec(appSecret.getBytes(), mac.getAlgorithm());
            mac.init(secretKeySpec);
            byte[] mysig = mac.doFinal(encodedPayload.getBytes());

            return Arrays.equals(mysig, base64.decode(encodedSignature));
        } catch (InvalidKeyException e) {
            // Ignore
        } catch (NoSuchAlgorithmException e) {
            // Ignore
        }
        return false;
    }

Some comments about the code:

  • The Base64 class is the Jakarta Commons Base64 implementation, in urlSafe-mode
  • 'mysig' is generated using the Facebook App Secret for your Facebook Application and the Base64Url-encoded JSON-payload, NOT the decoded version (as I thought...)
  • It should work :-)
Hope this helps!

Inga kommentarer:

Skicka en kommentar