]> git.openstreetmap.org Git - osqa.git/blob - forum_modules/facebookauth/authentication.py
More data handled by the exporter, and a improved "pickled" value parsing.
[osqa.git] / forum_modules / facebookauth / authentication.py
1 import hashlib
2 from time import time
3 from datetime import datetime
4 from urllib import urlopen,  urlencode
5 from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
6 from django.utils.translation import ugettext as _
7
8 import settings
9
10 try:
11     from json import load as load_json
12 except:
13     from django.utils.simplejson import JSONDecoder
14
15     def load_json(json):
16         decoder = JSONDecoder()
17         return decoder.decode(json.read())
18
19 REST_SERVER = 'http://api.facebook.com/restserver.php'
20
21 class FacebookAuthConsumer(AuthenticationConsumer):
22     
23     def process_authentication_request(self, request):
24         API_KEY = str(settings.FB_API_KEY)
25
26         if API_KEY in request.COOKIES:
27             if self.check_cookies_signature(request.COOKIES):
28                 if self.check_session_expiry(request.COOKIES):
29                     return request.COOKIES[API_KEY + '_user']
30                 else:
31                     raise InvalidAuthentication(_('Sorry, your Facebook session has expired, please try again'))
32             else:
33                 raise InvalidAuthentication(_('The authentication with Facebook connect failed due to an invalid signature'))
34         else:
35             raise InvalidAuthentication(_('The authentication with Facebook connect failed, cannot find authentication tokens'))
36
37     def generate_signature(self, values):
38         keys = []
39
40         for key in sorted(values.keys()):
41             keys.append(key)
42
43         signature = ''.join(['%s=%s' % (key,  values[key]) for key in keys]) + str(settings.FB_APP_SECRET)
44         return hashlib.md5(signature).hexdigest()
45
46     def check_session_expiry(self, cookies):
47         return datetime.fromtimestamp(float(cookies[settings.FB_API_KEY+'_expires'])) > datetime.now()
48
49     def check_cookies_signature(self, cookies):
50         API_KEY = str(settings.FB_API_KEY)
51
52         values = {}
53
54         for key in cookies.keys():
55             if (key.startswith(API_KEY + '_')):
56                 values[key.replace(API_KEY + '_',  '')] = cookies[key]
57
58         return self.generate_signature(values) == cookies[API_KEY]
59
60     def get_user_data(self, key):
61         request_data = {
62             'method': 'Users.getInfo',
63             'api_key': settings.FB_API_KEY,
64             'call_id': time(),
65             'v': '1.0',
66             'uids': key,
67             'fields': 'name,first_name,last_name,email',
68             'format': 'json',
69         }
70
71         request_data['sig'] = self.generate_signature(request_data)
72         fb_response = load_json(urlopen(REST_SERVER, urlencode(request_data)))[0]
73
74         return {
75             'username': fb_response['first_name'] + ' ' + fb_response['last_name'],
76             'email': fb_response['email']
77         }
78
79 class FacebookAuthContext(ConsumerTemplateContext):
80     mode = 'BIGICON'
81     type = 'CUSTOM'
82     weight = 100
83     human_name = 'Facebook'
84     code_template = 'modules/facebookauth/button.html'
85     extra_css = ["http://www.facebook.com/css/connect/connect_button.css"]
86
87     API_KEY = settings.FB_API_KEY