Skip to content

Commit

Permalink
Add Python 3 support for FacebookAuthorization.parse_signed_data
Browse files Browse the repository at this point in the history
`json.loads` was expecting a string, but in python 3 `base64decode()`
return bytes and that is why it bugged. We fix this by making sure
the decoded payload data is in string and that `hmac.new()` is
provided with arguments in bytes. `open_facebook.utils.smart_str`
will do that job correctly in python 2 and 3.

We also use `hmac.compare_digest()` which is the preferred way to
compare those kinds of data to prevent timing analysis. If not
`hmac.compare_digest` is available (python 2.7.7+) then we just compare
logically.

Fixes tschellenbach#491.
  • Loading branch information
stianpr committed Nov 10, 2014
1 parent fb692bd commit c899a8e
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions open_facebook/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,15 +464,15 @@ def parse_signed_data(cls, signed_request,
and
http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas
'''
from open_facebook.utils import base64_url_decode_php_style
from open_facebook.utils import base64_url_decode_php_style, smart_str
l = signed_request.split('.', 2)
encoded_sig = l[0]
payload = l[1]
from open_facebook.utils import json
sig = base64_url_decode_php_style(encoded_sig)
import hmac
import hashlib
data = json.loads(base64_url_decode_php_style(payload))
data = json.loads(base64_url_decode_php_style(payload).decode('utf-8'))

algo = data.get('algorithm').upper()
if algo != 'HMAC-SHA256':
Expand All @@ -482,10 +482,12 @@ def parse_signed_data(cls, signed_request,
logger.error('Unknown algorithm')
return None
else:
expected_sig = hmac.new(secret, msg=payload,
expected_sig = hmac.new(smart_str(secret), msg=smart_str(payload),
digestmod=hashlib.sha256).digest()

if sig != expected_sig:
if (hasattr(hmac, 'compare_digest') and
not hmac.compare_digest(sig, expected_sig) or
sig != expected_sig):
error_format = 'Signature %s didnt match the expected signature %s'
error_message = error_format % (sig, expected_sig)
send_warning(error_message)
Expand Down

0 comments on commit c899a8e

Please sign in to comment.