Subscribe to Updates

RSS RSS feed    What is this?

Email By email:

Privacy Assured more »

Topics

Search This Site

Follow on Facebook

 

« Hosting Facebook iFrame Canvas Pages on Cloudfront SOLVED | Main | Website Outage? Hosting Problem or DNS Problem? »
Thursday
May162013

Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion

Have you ever had one of the coding problems where the solution comes to you while you're sleeping? I had one of those which I've decided to document because despite extensive searching, I couldn't find anything close to a solution.

The Task Is This

To properly integrate Facebook's Login For The Web to permit your web app users to authenticate themselves in your app using Facebook, I believe that if your app needs any modicum of security, you should also verify the signature on the "Signed Request".

Sounds easy enough, Facebook even provides a PHP example.

With the release of ColdFusion 10, there's even a built-in hmac() function, but it's a bit buggy, and I couldn't get it to work with Railo 4. So I used the HMAC_SHA256() function posted on Summation Technologies' website, which should work across all ColdFusion versions and CFML servers.

Next, I slapped together some code that emulates what the PHP code does. First thing to address is the wonky modified Base64 for URL encoding that Facebook uses. Specifically, you have to swap the '-' and '_' characters back to '+' and '/' characters repectively. 

PHP base64_decode() vs CFML BinaryDecode() & ToBinary()

Regardless of what I tried, I couldn't get Coldfusion to recognize the Facebook Signature as being Base64-encoded:

<cfset binarysig = BinaryDecode( sig, "Base64")>

The error:

Ensure that the input was encoded with the same encoding as the one you are using to decode it with.

The PHP function base64_decode() had no problem at all decoding the string. So, after several hours, I called it a night which is when the solution came to me.

The Solution

I thought to try reversing the process. I took the hashed expected_sig and Base64 encoded it to see what the signature SHOULD look like.

Lo and behold, I got the exact same signature string I'd been trying to decode with one exception: it had an '=' character at the end! From the previously-linked Wiki article:

Some variants allow or require omitting the padding '=' signs to avoid them being confused with field separators.

Apparently, this is one of the "variants" that Facebook uses. The PHP base64_decode() function doesn't appear to have a problem with the missing padding, but the Coldfusion BinaryDecode() function certainly does.

The fix is easy enough, I simply appended a '=' and everything worked! Digging deeper into why the '=' is used at all when Base64-encoding revealed a few extra details which I've implemented in my solution below.

The CFML FacebookSignedRequestIsValid() Function

Here is my only moderately tested function:

<cffunction name="FacebookSignedRequestIsValid" returntype="boolean" access="private" output="false">
    <cfargument name="signedRequest" type="string" required="true" />
    <cfargument name="privateKey" type="string" required="false" default="389659060a49560552d87fd8281257fa" />
	<cfscript>
	var LOCAL = structnew();
	//Prepare the Signature
	LOCAL.sig = ListGetAt(arguments.signedRequest, 1, ".");
	LOCAL.sig = replace(LOCAL.sig, '-', '+', 'ALL');
	LOCAL.sig = replace(LOCAL.sig, '_', '/', 'ALL');
	//Add correct Base64 padding. See: http://en.wikipedia.org/wiki/Base64
	switch (len(LOCAL.sig) mod 3) {
		case 1: {LOCAL.sig = LOCAL.sig & '=='; break;}
		case 2: {LOCAL.sig = LOCAL.sig & '='; break;}
	}
	LOCAL.sig = LOCAL.sig & '='; 
	LOCAL.binarysig = BinaryDecode(LOCAL.sig, "Base64");
	LOCAL.sig = binaryEncode(LOCAL.binarysig, "hex" );
	//Prepare the Expected Signature
	LOCAL.payload = ListGetAt(arguments.signedRequest, 2, ".");
	LOCAL.expectedSig = HMAC_SHA256(data=LOCAL.payload, key=arguments.privateKey); // See: http://www.isummation.com/blog/calculate-hmac-sha256-digest-using-user-defined-function-in-coldfusion/
	//Test if match
	if (LOCAL.sig EQ LOCAL.expectedSig) LOCAL.result = true;
	else LOCAL.result = false;
	</cfscript>
    <cfreturn LOCAL.result>
</cffunction>

This function will likely prove itself useful with other oAuth implementations.

References (19)

References allow you to track sources for this article, as well as articles that were written in response to this article.
  • Response
    Response: casio ca003
    時計 価格
  • Response
    Response: indexing programs
    Nice Web site, Continue the excellent job. With thanks.
  • Response
    Response: rehab centers
    get greatest info on Domains Snippets available
  • Response
    get greatest posicionar web around
  • Response
    see here for top quality seo australia anywhere
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Response: dvnf
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Response: dvnf
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Response: dentist tempe
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Response: watch here
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -
  • Response
    Checking Facebook's HMAC-SHA256 Encode Signature Using ColdFusion - Webmastery Made Simple -

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>