if 'code' in self.data:
url = FACEBOOK_ACCESS_TOKEN_URL + '?' + \
urlencode({'client_id': settings.FACEBOOK_APP_ID,
- 'redirect_uri': self.redirect_uri,
- 'client_secret': settings.FACEBOOK_API_SECRET,
- 'code': self.data['code']})
+ 'redirect_uri': self.redirect_uri,
+ 'client_secret': settings.FACEBOOK_API_SECRET,
+ 'code': self.data['code']})
response = cgi.parse_qs(urlopen(url).read())
access_token = response['access_token'][0]
+ if 'expires' in response:
+ expires = response['expires'][0]
+
+ if 'signed_request' in self.data:
+ response = load_signed_request(self.data.get('signed_request'))
+
+ if response is not None:
+ access_token = response.get('access_token') or response.get('oauth_token')
+
+ if 'expires' in response:
+ expires = response['expires']
+
+ if 'session_key' in self.data:
+ params=['secret', 'uid', 'session_key', 'access_token', 'expires', 'base_domain']
+ params_dict = dict([(p, self.data[p]) for p in params])
+
+ sorted = params_dict.items()
+ sorted.sort(key=lambda x:x[0])
+
+ check_str = ''.join(["%s=%s"%(x[0], x[1]) for x in sorted]) + settings.FACEBOOK_API_SECRET
+ expected_sig = hashlib.md5(check_str).hexdigest()
+ sig = self.data['sig']
+
+ if sig == expected_sig:
+ access_token = params_dict['access_token']
+ expires = params_dict['expires']
+
+ if access_token:
data = self.user_data(access_token)
if data is not None:
if 'error' in data:
@classmethod
def enabled(cls):
"""Return backend enabled status by checking basic settings"""
- return all(hasattr(settings, name) for name in
- ('FACEBOOK_APP_ID',
- 'FACEBOOK_API_SECRET'))
+ return all(hasattr(settings, name) for name in ('FACEBOOK_APP_ID',
+ 'FACEBOOK_API_SECRET'))
+def base64_url_decode(data):
+ data = data.encode(u'ascii')
+ data += '=' * (4 - (len(data) % 4))
+ return base64.urlsafe_b64decode(data)
+
+def base64_url_encode(data):
+ return base64.urlsafe_b64encode(data).rstrip('=')
+
+def load_signed_request(signed_request):
+ try:
+ sig, payload = signed_request.split(u'.', 1)
+ sig = base64_url_decode(sig)
+ data = simplejson.loads(base64_url_decode(payload))
+
+ expected_sig = hmac.new(
+ settings.FACEBOOK_API_SECRET, msg=payload, digestmod=hashlib.sha256).digest()
+
+ # allow the signed_request to function for upto 1 day
+ if sig == expected_sig and \
+ data[u'issued_at'] > (time.time() - 86400):
+ return data
+ except ValueError, ex:
+ pass # ignore if can't split on dot
+
# Backend definition
BACKENDS = {
'facebook': FacebookAuth,