]> git.openstreetmap.org Git - osqa.git/commitdiff
adding support for the new Facebook oauth 2.0 authentication model
authorjordan <jordan@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Tue, 17 May 2011 20:36:25 +0000 (20:36 +0000)
committerjordan <jordan@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Tue, 17 May 2011 20:36:25 +0000 (20:36 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@1044 0cfe37f9-358a-4d5e-be75-b63607b5c754

forum/views/auth.py
forum_modules/facebookauth/authentication.py
forum_modules/facebookauth/templates/button.html
forum_modules/facebookauth/templates/xd_receiver.html [deleted file]
forum_modules/facebookauth/urls.py [deleted file]
forum_modules/facebookauth/views.py [deleted file]

index db8cc325ec58eb00b1d74ecdf9e21b73efac3f60..c0fecc1d5c0a315cfde32af24a0ec85705fc4aeb 100644 (file)
@@ -7,6 +7,7 @@ from forum.http_responses import HttpResponseUnauthorized
 from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext as _
 from django.utils.http import urlquote_plus
+from django.utils.encoding import smart_unicode
 from forum.views.decorators import login_required
 from forum.modules import decorate
 from django.contrib.auth import login, logout
@@ -197,7 +198,12 @@ def external_register(request):
             return HttpResponseRedirect(reverse('auth_signin'))
 
         provider_class = AUTH_PROVIDERS[auth_provider].consumer
-        user_data = provider_class.get_user_data(request.session['assoc_key'])
+
+        # Pass the cookies to the Facebook authentication class get_user_data method. We need them to take the access token.
+        if provider_class.__class__.__name__ == 'FacebookAuthConsumer':
+            user_data = provider_class.get_user_data(request.COOKIES)
+        else:
+            user_data = provider_class.get_user_data(request.session['assoc_key'])
 
         if not user_data:
             user_data = request.session.get('auth_consumer_data', {})
@@ -374,7 +380,7 @@ def login_and_forward(request, user, forward=None, message=None):
     login(request, user)
 
     if message is None:
-        message = _("Welcome back %s, you are now logged in") % user.username
+        message = _("Welcome back %s, you are now logged in") % smart_unicode(user.username)
 
     request.user.message_set.create(message=message)
 
index b19d79441369fb4239d43cbc1db8adc6a9f9a432..308c18cf45afbca502154e17b43105a2b202e765 100644 (file)
@@ -2,8 +2,10 @@ import hashlib
 from time import time
 from datetime import datetime
 from urllib import urlopen,  urlencode
+from urlparse import parse_qs
 from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
 from django.utils.translation import ugettext as _
+from django.utils.encoding import smart_unicode
 
 import settings
 
@@ -16,64 +18,39 @@ except:
         decoder = JSONDecoder()
         return decoder.decode(json.read())
 
-REST_SERVER = 'http://api.facebook.com/restserver.php'
-
 class FacebookAuthConsumer(AuthenticationConsumer):
     
     def process_authentication_request(self, request):
         API_KEY = str(settings.FB_API_KEY)
 
-        if API_KEY in request.COOKIES:
-            if self.check_cookies_signature(request.COOKIES):
-                if self.check_session_expiry(request.COOKIES):
-                    return request.COOKIES[API_KEY + '_user']
-                else:
-                    raise InvalidAuthentication(_('Sorry, your Facebook session has expired, please try again'))
+        # Check if the Facebook cookie has been received.
+        if 'fbs_%s' % API_KEY in request.COOKIES:
+            fbs_cookie = request.COOKIES['fbs_%s' % API_KEY]
+            parsed_fbs = parse_qs(smart_unicode(fbs_cookie))
+            self.parsed_fbs = parsed_fbs
+
+            # Check if the session hasn't expired.
+            if self.check_session_expiry(request.COOKIES):
+                return parsed_fbs['uid'][0]
             else:
-                raise InvalidAuthentication(_('The authentication with Facebook connect failed due to an invalid signature'))
+                raise InvalidAuthentication(_('Sorry, your Facebook session has expired, please try again'))
         else:
             raise InvalidAuthentication(_('The authentication with Facebook connect failed, cannot find authentication tokens'))
-
-    def generate_signature(self, values):
-        keys = []
-
-        for key in sorted(values.keys()):
-            keys.append(key)
-
-        signature = ''.join(['%s=%s' % (key,  values[key]) for key in keys]) + str(settings.FB_APP_SECRET)
-        return hashlib.md5(signature).hexdigest()
-
     def check_session_expiry(self, cookies):
-        return datetime.fromtimestamp(float(cookies[settings.FB_API_KEY+'_expires'])) > datetime.now()
+        return datetime.fromtimestamp(float(self.parsed_fbs['expires'][0])) > datetime.now()
 
-    def check_cookies_signature(self, cookies):
+    def get_user_data(self, cookies):
         API_KEY = str(settings.FB_API_KEY)
+        fbs_cookie = cookies['fbs_%s' % API_KEY]
+        parsed_fbs = parse_qs(smart_unicode(fbs_cookie))
 
-        values = {}
-
-        for key in cookies.keys():
-            if (key.startswith(API_KEY + '_')):
-                values[key.replace(API_KEY + '_',  '')] = cookies[key]
-
-        return self.generate_signature(values) == cookies[API_KEY]
-
-    def get_user_data(self, key):
-        request_data = {
-            'method': 'Users.getInfo',
-            'api_key': settings.FB_API_KEY,
-            'call_id': time(),
-            'v': '1.0',
-            'uids': key,
-            'fields': 'name,first_name,last_name,email',
-            'format': 'json',
-        }
-
-        request_data['sig'] = self.generate_signature(request_data)
-        fb_response = load_json(urlopen(REST_SERVER, urlencode(request_data)))[0]
+        # Communicate with the access token to the Facebook oauth interface.
+        json = load_json(urlopen('https://graph.facebook.com/me?access_token=%s' % parsed_fbs['access_token'][0]))
 
+        # Return the user data.
         return {
-            'username': fb_response['first_name'] + ' ' + fb_response['last_name'],
-            'email': fb_response['email']
+            'username': '%s %s' % (smart_unicode(json['first_name']), smart_unicode(json['last_name'])),
+            'email': smart_unicode(json['email']),
         }
 
 class FacebookAuthContext(ConsumerTemplateContext):
index ceae1fc2e17ac9ba78f1a67e857a24c17703a110..ba03a30e88f58a2cf9cabb20c47dfa9642807015 100644 (file)
@@ -1,38 +1,32 @@
-<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>\r
-<script type="text/javascript">\r
-    var FB_API_KEY = "{{ provider.API_KEY }}";\r
-    var FB_CHANNEL_PATH = "{% url  xd_receiver %}";\r
-\r
-    FB.init(FB_API_KEY, FB_CHANNEL_PATH, {permsToRequestOnConnect : "email"});\r
+{% load extra_tags %}\r
 \r
-    function FB_ConnectPostAuthorization() {\r
-        if ($('#validate_email').attr('checked')) {\r
-            FB_RequireFeatures(["Api"], function(){\r
-                var api = FB.Facebook.apiClient;\r
-                var fb_uid = api.get_session().uid;\r
+<div id="fb-root"></div>\r
+<script src="http://connect.facebook.net/en_US/all.js"></script>\r
+<script>\r
+    var FB_API_KEY = "{{ provider.API_KEY }}";\r
+    FB.init({\r
+        appId:FB_API_KEY, cookie:true,\r
+        status:true, xfbml:true\r
+    });\r
 \r
-                $.post('{% url  facebook_user_is_registered %}', {'fb_uid': fb_uid}, function(response) {\r
-                    if (response != "yes") {\r
-                        api.users_hasAppPermission("email", function(result) {\r
-                            if (!result) {\r
-                                FB.Connect.showPermissionDialog("email", redirect_to_done_page);\r
-                            } else {\r
-                                redirect_to_done_page()\r
-                            }\r
-                        })\r
+    function check_login_status() {\r
+        FB.getLoginStatus(function(response) {\r
+            if (response.session) {\r
+                redirect_to_done_page();\r
+            } else {\r
+                FB.login(function(response) {\r
+                    if (response.session) {\r
+                      redirect_to_done_page();\r
                     } else {\r
-                        redirect_to_done_page()\r
+                      // user cancelled login\r
                     }\r
                 });\r
-            });\r
-        } else {\r
-            redirect_to_done_page();\r
-        }\r
+            }\r
+        });\r
     }\r
 \r
     function redirect_to_done_page() {\r
         window.location = "{% url auth_provider_done provider=provider.id %}";\r
     }\r
-\r
 </script>\r
-<fb:login-button v="2" size="medium" onlogin="FB_ConnectPostAuthorization()">Facebook</fb:login-button>
\ No newline at end of file
+<a style="position: relative; top: -8px;" href="javascript:void(0);" onclick="check_login_status()" perms="email"><img src="{% media '/media/images/openid/facebook.gif' %}" /></a>\r
diff --git a/forum_modules/facebookauth/templates/xd_receiver.html b/forum_modules/facebookauth/templates/xd_receiver.html
deleted file mode 100644 (file)
index 9c1664d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <body> <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script> </body> </html>\r
diff --git a/forum_modules/facebookauth/urls.py b/forum_modules/facebookauth/urls.py
deleted file mode 100644 (file)
index cbe3b6c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-from django.conf.urls.defaults import *
-from django.views.generic.simple import direct_to_template
-
-from views import user_is_registered
-
-urlpatterns = patterns('',
-    url(r'^xd_receiver.htm$',  direct_to_template,  {'template': 'modules/facebookauth/xd_receiver.html'}, name='xd_receiver'),
-    url(r'^facebook/user_is_registered/', user_is_registered, name="facebook_user_is_registered"),
-)
\ No newline at end of file
diff --git a/forum_modules/facebookauth/views.py b/forum_modules/facebookauth/views.py
deleted file mode 100644 (file)
index f77c628..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-from forum.models import AuthKeyUserAssociation
-from django.http import HttpResponse
-
-def user_is_registered(request):
-    try:
-        fb_uid = request.POST['fb_uid']
-        #print fb_uid
-        AuthKeyUserAssociation.objects.get(key=fb_uid)
-        return HttpResponse('yes')
-    except:
-        return HttpResponse('no')
\ No newline at end of file