summaryrefslogtreecommitdiffstats
path: root/askbot/deps
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-12-23 01:52:07 -0300
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-12-23 01:52:07 -0300
commit661460d593d32cbc91382b30dbb2a4034701114f (patch)
tree9276e0d1b4aadff50c8723d7e73837b2dbed1293 /askbot/deps
parent1819a86eeed5dd3978a7f66ac168410bb20f7c53 (diff)
downloadaskbot-661460d593d32cbc91382b30dbb2a4034701114f.tar.gz
askbot-661460d593d32cbc91382b30dbb2a4034701114f.tar.bz2
askbot-661460d593d32cbc91382b30dbb2a4034701114f.zip
first pass on fixing facebook login, "approve" path works
Diffstat (limited to 'askbot/deps')
-rw-r--r--askbot/deps/django_authopenid/backends.py2
-rw-r--r--askbot/deps/django_authopenid/forms.py3
-rw-r--r--askbot/deps/django_authopenid/urls.py5
-rw-r--r--askbot/deps/django_authopenid/util.py88
-rw-r--r--askbot/deps/django_authopenid/views.py88
5 files changed, 101 insertions, 85 deletions
diff --git a/askbot/deps/django_authopenid/backends.py b/askbot/deps/django_authopenid/backends.py
index 1e8626ac..f719e811 100644
--- a/askbot/deps/django_authopenid/backends.py
+++ b/askbot/deps/django_authopenid/backends.py
@@ -145,7 +145,7 @@ class AuthBackend(object):
return None
elif method == 'oauth':
- if login_providers[provider_name]['type'] == 'oauth':
+ if login_providers[provider_name]['type'] in ('oauth', 'oauth2'):
try:
assoc = UserAssociation.objects.get(
openid_url = oauth_user_id,
diff --git a/askbot/deps/django_authopenid/forms.py b/askbot/deps/django_authopenid/forms.py
index 3c0e8e7f..f8822877 100644
--- a/askbot/deps/django_authopenid/forms.py
+++ b/askbot/deps/django_authopenid/forms.py
@@ -212,7 +212,8 @@ class LoginForm(forms.Form):
self.cleaned_data['login_type'] = 'openid'
elif provider_type == 'oauth':
self.cleaned_data['login_type'] = 'oauth'
- pass
+ elif provider_type == 'oauth2':
+ self.cleaned_data['login_type'] = 'oauth2'
elif provider_type == 'facebook':
self.cleaned_data['login_type'] = 'facebook'
#self.do_clean_oauth_fields()
diff --git a/askbot/deps/django_authopenid/urls.py b/askbot/deps/django_authopenid/urls.py
index 1b7d0b01..1d07aa94 100644
--- a/askbot/deps/django_authopenid/urls.py
+++ b/askbot/deps/django_authopenid/urls.py
@@ -19,6 +19,11 @@ urlpatterns = patterns('askbot.deps.django_authopenid.views',
'complete_oauth_signin',
name='user_complete_oauth_signin'
),
+ url(
+ r'^signin/complete-oauth2/',
+ 'complete_oauth2_signin',
+ name='user_complete_oauth2_signin'
+ ),
url(r'^%s$' % _('register/'), 'register', name='user_register'),
url(
r'^%s$' % _('signup/'),
diff --git a/askbot/deps/django_authopenid/util.py b/askbot/deps/django_authopenid/util.py
index e003c493..72ee09df 100644
--- a/askbot/deps/django_authopenid/util.py
+++ b/askbot/deps/django_authopenid/util.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import cgi
import urllib
-import urllib2
+import urlparse
import functools
import re
import random
@@ -9,10 +9,11 @@ from openid.store.interface import OpenIDStore
from openid.association import Association as OIDAssociation
from openid.extensions import sreg
from openid import store as openid_store
-import oauth2 as oauth
+import oauth2 as oauth # OAuth1 protocol
from django.db.models.query import Q
from django.conf import settings
+from django.core.urlresolvers import reverse
from django.utils import simplejson
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext as _
@@ -386,12 +387,23 @@ def get_enabled_major_login_providers():
'password_changeable': True
}
+ def get_facebook_user_id(client):
+ """returns facebook user id given the access token"""
+ profile = client.request('me')
+ return profile['id']
+
if askbot_settings.FACEBOOK_KEY and askbot_settings.FACEBOOK_SECRET:
data['facebook'] = {
'name': 'facebook',
'display_name': 'Facebook',
- 'type': 'facebook',
+ 'type': 'oauth2',
+ 'auth_endpoint': 'https://www.facebook.com/dialog/oauth/',
+ 'token_endpoint': 'https://graph.facebook.com/oauth/access_token',
+ 'resource_endpoint': 'https://graph.facebook.com/',
'icon_media_path': '/jquery-openid/images/facebook.gif',
+ 'get_user_id_function': get_facebook_user_id,
+ 'response_parser': lambda data: dict(urlparse.parse_qsl(data))
+
}
if askbot_settings.TWITTER_KEY and askbot_settings.TWITTER_SECRET:
data['twitter'] = {
@@ -666,8 +678,11 @@ def get_oauth_parameters(provider_name):
elif provider_name == 'identi.ca':
consumer_key = askbot_settings.IDENTICA_KEY
consumer_secret = askbot_settings.IDENTICA_SECRET
+ elif provider_name == 'facebook':
+ consumer_key = askbot_settings.FACEBOOK_KEY
+ consumer_secret = askbot_settings.FACEBOOK_SECRET
else:
- raise ValueError('sorry, only linkedin and twitter oauth for now')
+ raise ValueError('unexpected oauth provider %s' % provider_name)
data['consumer_key'] = consumer_key
data['consumer_secret'] = consumer_secret
@@ -781,62 +796,21 @@ class OAuthConnection(object):
return auth_url
-class FacebookError(Exception):
- """Raised when there's something not right
- with FacebookConnect
- """
- pass
+def get_oauth2_starter_url(provider_name):
+ """returns redirect url for the oauth2 protocol for a given provider"""
+ from sanction.client import Client
-def urlsafe_b64decode(input):
- length = len(input)
- return base64.urlsafe_b64decode(
- input.ljust(length + length % 4, '=')
+ providers = get_enabled_login_providers()
+ params = providers[provider_name]
+ client_id = getattr(askbot_settings, provider_name.upper() + '_KEY')
+ redirect_uri = askbot_settings.APP_URL + reverse('user_complete_oauth2_signin')
+ client = Client(
+ auth_endpoint=params['auth_endpoint'],
+ client_id=client_id,
+ redirect_uri=redirect_uri
)
+ return client.auth_uri()
-def parse_signed_facebook_request(signed_request, secret):
- """
- Parse signed_request given by Facebook (usually via POST),
- decrypt with app secret.
-
- Arguments:
- signed_request -- Facebook's signed request given through POST
- secret -- Application's app_secret required to decrpyt signed_request
-
- slightly edited copy from https://gist.github.com/1190267
- """
-
- if "." in signed_request:
- esig, payload = signed_request.split(".")
- else:
- return {}
-
- sig = urlsafe_b64decode(str(esig))
- data = simplejson.loads(urlsafe_b64decode(str(payload)))
-
- if not isinstance(data, dict):
- raise ValueError("Pyload is not a json string!")
- return {}
-
- if data["algorithm"].upper() == "HMAC-SHA256":
- if hmac.new(str(secret), str(payload), hashlib.sha256).digest() == sig:
- return data
- else:
- raise ValueError("Not HMAC-SHA256 encrypted!")
-
- return {}
-
-def get_facebook_user_id(request):
- try:
- key = askbot_settings.FACEBOOK_KEY
- fb_cookie = request.COOKIES['fbsr_%s' % key]
- if not fb_cookie:
- raise ValueError('cannot access facebook cookie')
-
- secret = askbot_settings.FACEBOOK_SECRET
- response = parse_signed_facebook_request(fb_cookie, secret)
- return response['user_id']
- except Exception, e:
- raise FacebookError(e)
def ldap_check_password(username, password):
import ldap
diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py
index 1d1a9a57..a7dcabb8 100644
--- a/askbot/deps/django_authopenid/views.py
+++ b/askbot/deps/django_authopenid/views.py
@@ -54,6 +54,7 @@ from recaptcha_works.decorators import fix_recaptcha_remote_ip
from askbot.deps.django_authopenid.ldap_auth import ldap_create_user
from askbot.deps.django_authopenid.ldap_auth import ldap_authenticate
from askbot.utils.loading import load_module
+from sanction.client import Client as OAuth2Client
from urlparse import urlparse
from openid.consumer.consumer import Consumer, \
@@ -265,6 +266,58 @@ def not_authenticated(func):
return func(request, *args, **kwargs)
return decorated
+def complete_oauth2_signin(request):
+ if 'next_url' in request.session:
+ next_url = request.session['next_url']
+ del request.session['next_url']
+ else:
+ next_url = reverse('index')
+
+ providers = util.get_enabled_login_providers()
+ try:
+ provider_name = request.session['provider_name']
+ params = providers[provider_name]
+ assert(params['type'] == 'oauth2')
+ except Exception:
+ return HttpResponseBadRequest()
+
+ client_id = getattr(askbot_settings, provider_name.upper() + '_KEY')
+ client_secret = getattr(askbot_settings, provider_name.upper() + '_SECRET')
+
+ client = OAuth2Client(
+ token_endpoint=params['token_endpoint'],
+ resource_endpoint=params['resource_endpoint'],
+ redirect_uri=askbot_settings.APP_URL + reverse('user_complete_oauth2_signin'),
+ client_id=client_id,
+ client_secret=client_secret
+ )
+
+ client.request_token(code=request.GET['code'], parser=params['response_parser'])
+
+ #todo: possibly set additional parameters here
+ user_id = params['get_user_id_function'](client)
+
+ user = authenticate(
+ oauth_user_id = user_id,
+ provider_name = provider_name,
+ method = 'oauth'
+ )
+
+ logging.debug('finalizing oauth signin')
+
+ request.session['email'] = ''#todo: pull from profile
+ request.session['username'] = ''#todo: pull from profile
+
+ return finalize_generic_signin(
+ request = request,
+ user = user,
+ user_identifier = user_id,
+ login_provider_name = provider_name,
+ redirect_url = next_url
+ )
+
+
+
def complete_oauth_signin(request):
if 'next_url' in request.session:
next_url = request.session['next_url']
@@ -480,12 +533,10 @@ def signin(request, template_name='authopenid/signin.html'):
elif login_form.cleaned_data['login_type'] == 'oauth':
try:
#this url may need to have "next" piggibacked onto
- callback_url = reverse('user_complete_oauth_signin')
-
connection = util.OAuthConnection(
- provider_name,
- callback_url = callback_url
- )
+ provider_name,
+ callback_url=reverse('user_complete_oauth_signin')
+ )
connection.start()
@@ -504,32 +555,17 @@ def signin(request, template_name='authopenid/signin.html'):
) % {'provider': provider_name}
request.user.message_set.create(message = msg)
- elif login_form.cleaned_data['login_type'] == 'facebook':
- #have to redirect for consistency
- #there is a requirement that 'complete_signin'
+ elif login_form.cleaned_data['login_type'] == 'oauth2':
try:
- #this call may raise FacebookError
- user_id = util.get_facebook_user_id(request)
-
- user = authenticate(
- method = 'facebook',
- facebook_user_id = user_id
- )
-
- return finalize_generic_signin(
- request = request,
- user = user,
- user_identifier = user_id,
- login_provider_name = provider_name,
- redirect_url = next_url
- )
-
- except util.FacebookError, e:
+ redirect_url = util.get_oauth2_starter_url(provider_name)
+ request.session['provider_name'] = provider_name
+ return HttpResponseRedirect(redirect_url)
+ except util.OAuthError, e:
logging.critical(unicode(e))
msg = _('Unfortunately, there was some problem when '
'connecting to %(provider)s, please try again '
'or use another provider'
- ) % {'provider': 'Facebook'}
+ ) % {'provider': provider_name}
request.user.message_set.create(message = msg)
elif login_form.cleaned_data['login_type'] == 'wordpress_site':