Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'psa2'

Conflicts:
	social_auth/__init__.py
  • Loading branch information...
commit a904272f3a41b2be80c345ba10bc09eb811dfadb 2 parents 1a72e33 + ac0bd7e
@omab authored
Showing with 491 additions and 9,546 deletions.
  1. +6 −0 README.rst
  2. 0  contrib/__init__.py
  3. 0  contrib/models.py
  4. +0 −1  contrib/tests/__init__.py
  5. +0 −18 contrib/tests/runtests.py
  6. +0 −162 contrib/tests/test_core.py
  7. +0 −27 contrib/tests/test_settings.py.template
  8. +6 −0 doc/index.rst
  9. +28 −16 example/app/facebook.py
  10. +11 −12 example/app/pipeline.py
  11. +2 −5 example/app/views.py
  12. +29 −18 example/app/vkontakte.py
  13. +23 −17 example/example/settings.py
  14. +1 −4 requirements.txt
  15. +1 −2  setup.py
  16. +9 −1 social_auth/__init__.py
  17. +4 −42 social_auth/admin.py
  18. +8 −996 social_auth/backends/__init__.py
  19. +1 −94 social_auth/backends/amazon.py
  20. +1 −28 social_auth/backends/aol.py
  21. +1 −92 social_auth/backends/browserid.py
  22. +1 −76 social_auth/backends/contrib/angel.py
  23. +2 −66 social_auth/backends/contrib/appsfuel.py
  24. +1 −68 social_auth/backends/contrib/behance.py
  25. +1 −22 social_auth/backends/contrib/belgiumeid.py
  26. +1 −113 social_auth/backends/contrib/bitbucket.py
  27. +1 −87 social_auth/backends/contrib/dailymotion.py
  28. +1 −80 social_auth/backends/contrib/disqus.py
  29. +2 −128 social_auth/backends/contrib/douban.py
  30. +1 −80 social_auth/backends/contrib/dropbox.py
  31. +5 −116 social_auth/backends/contrib/evernote.py
  32. +1 −124 social_auth/backends/contrib/exacttarget.py
  33. +1 −29 social_auth/backends/contrib/fedora.py
  34. +1 −89 social_auth/backends/contrib/fitbit.py
  35. +1 −92 social_auth/backends/contrib/flickr.py
  36. +1 −59 social_auth/backends/contrib/foursquare.py
  37. +1 −67 social_auth/backends/contrib/gae.py
  38. +5 −137 social_auth/backends/contrib/github.py
  39. +1 −72 social_auth/backends/contrib/instagram.py
  40. +1 −82 social_auth/backends/contrib/jawbone.py
  41. +2 −200 social_auth/backends/contrib/linkedin.py
  42. +1 −94 social_auth/backends/contrib/live.py
  43. +1 −49 social_auth/backends/contrib/livejournal.py
  44. +1 −110 social_auth/backends/contrib/mailru.py
  45. +1 −68 social_auth/backends/contrib/mendeley.py
  46. +1 −58 social_auth/backends/contrib/mixcloud.py
  47. +3 −277 social_auth/backends/contrib/odnoklassniki.py
  48. +1 −87 social_auth/backends/contrib/orkut.py
  49. +2 −127 social_auth/backends/contrib/rdio.py
  50. +1 −106 social_auth/backends/contrib/readability.py
  51. +1 −124 social_auth/backends/contrib/shopify.py
  52. +1 −80 social_auth/backends/contrib/skyrock.py
  53. +1 −116 social_auth/backends/contrib/soundcloud.py
  54. +2 −117 social_auth/backends/contrib/stackoverflow.py
  55. +1 −67 social_auth/backends/contrib/stocktwits.py
  56. +1 −106 social_auth/backends/contrib/trello.py
  57. +1 −70 social_auth/backends/contrib/tripit.py
  58. +1 −121 social_auth/backends/contrib/tumblr.py
  59. +1 −77 social_auth/backends/contrib/twilio.py
  60. +3 −310 social_auth/backends/contrib/vk.py
  61. +7 −2 social_auth/backends/contrib/vkontakte.py
  62. +1 −80 social_auth/backends/contrib/weibo.py
  63. +1 −111 social_auth/backends/contrib/xing.py
  64. +1 −110 social_auth/backends/contrib/yahoo.py
  65. +1 −106 social_auth/backends/contrib/yammer.py
  66. +1 −27 social_auth/backends/contrib/yammer_staging.py
  67. +3 −165 social_auth/backends/contrib/yandex.py
  68. +19 −299 social_auth/backends/facebook.py
  69. +3 −275 social_auth/backends/google.py
  70. +1 −23 social_auth/backends/pipeline/associate.py
  71. +2 −16 social_auth/backends/pipeline/misc.py
  72. +3 −0  social_auth/backends/pipeline/sauth.py
  73. +0 −66 social_auth/backends/pipeline/social.py
  74. +3 −134 social_auth/backends/pipeline/user.py
  75. +1 −82 social_auth/backends/reddit.py
  76. +1 −78 social_auth/backends/steam.py
  77. +1 −87 social_auth/backends/stripe.py
  78. +1 −99 social_auth/backends/twitter.py
  79. +0 −48 social_auth/backends/utils.py
  80. +1 −29 social_auth/backends/yahoo.py
  81. +31 −50 social_auth/context_processors.py
  82. 0  social_auth/db/__init__.py
  83. +0 −272 social_auth/db/base.py
  84. +0 −100 social_auth/db/django_models.py
  85. +0 −106 social_auth/db/mongoengine_models.py
  86. +0 −41 social_auth/decorators.py
  87. +1 −101 social_auth/exceptions.py
  88. +1 −65 social_auth/fields.py
  89. BIN  social_auth/locale/de/LC_MESSAGES/django.mo
  90. +0 −46 social_auth/locale/de/LC_MESSAGES/django.po
  91. BIN  social_auth/locale/ru/LC_MESSAGES/django.mo
  92. +0 −38 social_auth/locale/ru/LC_MESSAGES/django.po
  93. BIN  social_auth/locale/tr/LC_MESSAGES/django.mo
  94. +0 −33 social_auth/locale/tr/LC_MESSAGES/django.po
  95. 0  social_auth/management/__init__.py
  96. 0  social_auth/management/commands/__init__.py
  97. +0 −32 social_auth/management/commands/clean_associations.py
  98. +0 −20 social_auth/management/commands/clean_nonces.py
  99. +2 −60 social_auth/middleware.py
  100. +1 −1  social_auth/migrations/0001_initial.py
  101. +31 −10 social_auth/models.py
  102. +0 −9 social_auth/signals.py
  103. +0 −44 social_auth/store.py
  104. +154 −0 social_auth/strategy.py
  105. +0 −14 social_auth/tests/__init__.py
  106. +0 −175 social_auth/tests/base.py
  107. +0 −169 social_auth/tests/client.py
  108. +0 −88 social_auth/tests/facebook.py
  109. +0 −82 social_auth/tests/google.py
  110. +0 −154 social_auth/tests/odnoklassniki.py
  111. +0 −79 social_auth/tests/twitter.py
  112. +6 −9 social_auth/urls.py
  113. +2 −251 social_auth/utils.py
  114. +24 −174 social_auth/views.py
View
6 README.rst
@@ -1,3 +1,7 @@
+**NOTE: THIS LIBRARY IS DEPRECATED IN FAVOR OF** `python-social-auth`_. **RIGHT NOW
+THIS LIBRARY DEPENDS DIRECTLY ON** `python-social-auth`_ **AND SHOULD BE CONSIDERED
+AS A MIGRATION STEP**
+
Django Social Auth
==================
@@ -10,6 +14,7 @@ third parties.
You can view this app's documentation on `Read the Docs`_ too.
+
.. contents:: Table of Contents
@@ -214,3 +219,4 @@ Some bits were derived from others' work and copyrighted by:
.. _Fedora OpenID: https://fedoraproject.org/wiki/OpenID
.. _Exacttarget HubExchange: http://code.exacttarget.com/
.. _Appsfuel OAuth2: http://docs.appsfuel.com/api_reference#api_reference
+.. _python-social-auth: https://github.com/omab/python-social-auth
View
0  contrib/__init__.py
No changes.
View
0  contrib/models.py
No changes.
View
1  contrib/tests/__init__.py
@@ -1 +0,0 @@
-from test_core import BackendsTest
View
18 contrib/tests/runtests.py
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-from os.path import dirname, abspath
-
-
-os.environ['DJANGO_SETTINGS_MODULE'] = 'test_settings'
-
-parent = dirname(dirname(dirname(abspath(__file__))))
-sys.path.insert(0, parent)
-
-from django.test.simple import DjangoTestSuiteRunner
-
-
-if __name__ == '__main__':
- DjangoTestSuiteRunner(failfast=False).run_tests(
- ['contrib.BackendsTest'], verbosity=1, interactive=True)
View
162 contrib/tests/test_core.py
@@ -1,162 +0,0 @@
-# -*- coding: utf-8 -*-
-import urlparse
-
-from selenium import webdriver
-
-from django.test import TestCase
-from django.conf import settings
-
-
-class BackendsTest(TestCase):
- def setUp(self):
- self.driver = webdriver.Firefox()
-
- def tearDown(self):
- self.driver.quit()
-
- def url(self, path):
- return urlparse.urljoin(settings.TEST_DOMAIN, path)
-
- def test_twitter_backend(self):
- # We grab the Twitter testing user details from settings file
- TEST_TWITTER_USER = getattr(settings, 'TEST_TWITTER_USER', None)
- TEST_TWITTER_PASSWORD = getattr(settings, 'TEST_TWITTER_PASSWORD',
- None)
- self.assertTrue(TEST_TWITTER_USER)
- self.assertTrue(TEST_TWITTER_PASSWORD)
-
- self.driver.get(self.url('/login/twitter/'))
-
- # We log in
- username_field = self.driver.find_element_by_id('username_or_email')
- username_field.send_keys(TEST_TWITTER_USER)
-
- password_field = self.driver.find_element_by_id('password')
- password_field.send_keys(TEST_TWITTER_PASSWORD)
- password_field.submit()
-
- # The application might be already allowed
- try:
- self.driver.find_element_by_id('allow').click()
- except:
- pass
-
- # We check the user logged in
- heading = self.driver.find_element_by_id('heading')
- if not heading.text == u'Logged in!':
- raise Exception('The user didn\'t log in')
-
- # Here we could test the User's fields
-
- def test_google_oauth_backend(self):
- TEST_GOOGLE_USER = getattr(settings, 'TEST_GOOGLE_USER', None)
- TEST_GOOGLE_PASSWORD = getattr(settings, 'TEST_GOOGLE_PASSWORD', None)
- self.assertTrue(TEST_GOOGLE_USER)
- self.assertTrue(TEST_GOOGLE_PASSWORD)
-
- self.driver.get(self.url('/login/google-oauth/'))
-
- # We log in
- username_field = self.driver.find_element_by_id('Email')
- username_field.send_keys(TEST_GOOGLE_USER)
-
- password_field = self.driver.find_element_by_id('Passwd')
- password_field.send_keys(TEST_GOOGLE_PASSWORD)
- password_field.submit()
-
- # The application might be already allowed
- try:
- self.driver.find_element_by_id('allow').click()
- except:
- pass
-
- # We check the user logged in
- heading = self.driver.find_element_by_id('heading')
- if not heading.text == u'Logged in!':
- raise Exception('The user didn\'t log in')
-
- # Here we could test the User's fields
-
- def test_google_oauth2_backend(self):
- TEST_GOOGLE_USER = getattr(settings, 'TEST_GOOGLE_USER', None)
- TEST_GOOGLE_PASSWORD = getattr(settings, 'TEST_GOOGLE_PASSWORD', None)
- self.assertTrue(TEST_GOOGLE_USER)
- self.assertTrue(TEST_GOOGLE_PASSWORD)
-
- self.driver.get(self.url('/login/google-oauth2/'))
-
- # We log in
- username_field = self.driver.find_element_by_id('Email')
- username_field.send_keys(TEST_GOOGLE_USER)
-
- password_field = self.driver.find_element_by_id('Passwd')
- password_field.send_keys(TEST_GOOGLE_PASSWORD)
- password_field.submit()
-
- # The application might be already allowed
- try:
- self.driver.find_element_by_id('submit_approve_access').click()
- except:
- pass
-
- # We check the user logged in
- heading = self.driver.find_element_by_id('heading')
- if not heading.text == u'Logged in!':
- raise Exception('The user didn\'t log in')
-
- # Here we could test the User's fields
-
- def test_facebook_backend(self):
- TEST_FACEBOOK_USER = getattr(settings, 'TEST_FACEBOOK_USER', None)
- TEST_FACEBOOK_PASSWORD = getattr(settings, 'TEST_FACEBOOK_PASSWORD',
- None)
- self.assertTrue(TEST_FACEBOOK_USER)
- self.assertTrue(TEST_FACEBOOK_PASSWORD)
-
- self.driver.get(self.url('/login/facebook/'))
-
- # We log in
- username_field = self.driver.find_element_by_id('email')
- username_field.send_keys(TEST_FACEBOOK_USER)
-
- password_field = self.driver.find_element_by_id('pass')
- password_field.send_keys(TEST_FACEBOOK_PASSWORD)
- password_field.submit()
-
- try:
- self.driver.find_element_by_name('grant_clicked').click()
- except:
- pass
-
- # We check the user logged in
- heading = self.driver.find_element_by_id('heading')
- if not heading.text == u'Logged in!':
- raise Exception('The user didn\'t log in')
-
- # Here we could test the User's fields
-
- def test_linkedin_backend(self):
- TEST_LINKEDIN_USER = getattr(settings, 'TEST_LINKEDIN_USER', None)
- TEST_LINKEDIN_PASSWORD = getattr(settings, 'TEST_LINKEDIN_PASSWORD',
- None)
- self.assertTrue(TEST_LINKEDIN_USER)
- self.assertTrue(TEST_LINKEDIN_PASSWORD)
-
- self.driver.get(self.url('/login/linkedin/'))
-
- # We log in
- username_field = self.driver.find_element_by_id(
- 'session_key-oauthAuthorizeForm')
- username_field.send_keys(TEST_LINKEDIN_USER)
-
- password_field = self.driver.find_element_by_id(
- 'session_password-oauthAuthorizeForm')
- password_field.send_keys(TEST_LINKEDIN_PASSWORD)
- password_field.submit()
-
- # We check the user logged in
- heading = self.driver.find_element_by_id('heading')
- if not heading.text == u'Logged in!':
- raise Exception('The user didn\'t log in')
-
- # Here we could test the User's fields
View
27 contrib/tests/test_settings.py.template
@@ -1,27 +0,0 @@
-import os
-
-BASE_DIR = os.path.dirname(__file__)
-
-INSTALLED_APPS = (
- 'contrib',
-)
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- }
-}
-
-TEST_DOMAIN = 'http://social.matiasaguirre.net'
-
-TEST_TWITTER_USER = ''
-TEST_TWITTER_PASSWORD = ''
-
-TEST_GOOGLE_USER = ''
-TEST_GOOGLE_PASSWORD = ''
-
-TEST_FACEBOOK_USER = ''
-TEST_FACEBOOK_PASSWORD = ''
-
-TEST_LINKEDIN_USER = ''
-TEST_LINKEDIN_PASSWORD = ''
View
6 doc/index.rst
@@ -1,6 +1,10 @@
Welcome to Django Social Auth's documentation!
==============================================
+**NOTE: THIS LIBRARY IS DEPRECATED IN FAVOR OF** `python-social-auth`_. **RIGHT NOW
+THIS LIBRARY DEPENDS DIRECTLY ON** `python-social-auth`_ **AND SHOULD BE CONSIDERED
+AS A MIGRATION STEP**
+
Django Social Auth is an easy to setup social authentication/authorization
mechanism for Django projects.
@@ -36,3 +40,5 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+
+.. _python-social-auth: https://github.com/omab/python-social-auth
View
44 example/app/facebook.py
@@ -1,3 +1,4 @@
+from django.conf import settings
from django.contrib.auth import BACKEND_SESSION_KEY
from django.contrib.auth.models import AnonymousUser
from django.http import HttpResponse
@@ -9,11 +10,15 @@
from social_auth.models import UserSocialAuth
from social_auth.views import complete as social_complete
-from social_auth.utils import setting
-from social_auth.backends.facebook import load_signed_request, FacebookBackend
+from social_auth.backends.facebook import FacebookBackend
+
def is_complete_authentication(request):
- return request.user.is_authenticated() and FacebookBackend.__name__ in request.session.get(BACKEND_SESSION_KEY, '')
+ return request.user.is_authenticated() and \
+ FacebookBackend.__name__ in request.session.get(
+ BACKEND_SESSION_KEY, ''
+ )
+
def get_access_token(user):
key = str(user.id)
@@ -23,7 +28,9 @@ def get_access_token(user):
if access_token is None:
try:
social_user = user.social_user if hasattr(user, 'social_user') \
- else UserSocialAuth.objects.get(user=user.id, provider=FacebookBackend.name)
+ else UserSocialAuth.objects.get(
+ user=user.id, provider=FacebookBackend.name
+ )
except UserSocialAuth.DoesNotExist:
return None
@@ -31,33 +38,37 @@ def get_access_token(user):
access_token = social_user.extra_data.get('access_token')
expires = social_user.extra_data.get('expires')
- cache.set(key, access_token, int(expires) if expires is not None else 0)
-
+ cache.set(key, access_token, int(expires) if expires is not None
+ else 0)
return access_token
+
# Facebook decorator to setup environment
def facebook_decorator(func):
def wrapper(request, *args, **kwargs):
user = request.user
- # User must me logged via FB backend in order to ensure we talk about the same person
+ # User must me logged via FB backend in order to ensure we talk about
+ # the same person
if not is_complete_authentication(request):
try:
user = social_complete(request, FacebookBackend.name)
except ValueError:
- pass # no matter if failed
+ pass # no matter if failed
- # Not recommended way for FB, but still something we need to be aware of
+ # Not recommended way for FB, but still something we need to be aware
+ # of
if isinstance(user, HttpResponse):
kwargs.update({'auth_response': user})
- # Need to re-check the completion
- else:
+ else: # Need to re-check the completion
if is_complete_authentication(request):
kwargs.update({'access_token': get_access_token(request.user)})
else:
request.user = AnonymousUser()
- signed_request = load_signed_request(request.REQUEST.get('signed_request', ''))
+ signed_request = FacebookBackend().load_signed_request(
+ request.REQUEST.get('signed_request', '')
+ )
if signed_request:
kwargs.update({'signed_request': signed_request})
@@ -70,9 +81,10 @@ def wrapper(request, *args, **kwargs):
@facebook_decorator
def facebook_view(request, *args, **kwargs):
# If there is a ready response just return it. Not recommended though.
- auth_response = kwargs.get('auth_response')
+ auth_response = kwargs.get('auth_response')
if auth_response:
return auth_response
-
- return render_to_response('facebook.html', {'fb_app_id':setting('FACEBOOK_APP_ID'),
- 'warning': request.method == 'GET'}, RequestContext(request))
+ return render_to_response('facebook.html', {
+ 'fb_app_id': getattr(settings, 'FACEBOOK_APP_ID', None),
+ 'warning': request.method == 'GET'
+ }, RequestContext(request))
View
23 example/app/pipeline.py
@@ -1,27 +1,26 @@
from django.http import HttpResponseRedirect
-def redirect_to_form(*args, **kwargs):
- if not kwargs['request'].session.get('saved_username') and \
- kwargs.get('user') is None:
+def redirect_to_form(strategy, user=None, *args, **kwargs):
+ if not strategy.session_get('saved_username') and user is None:
return HttpResponseRedirect('/form/')
-def username(request, *args, **kwargs):
- if kwargs.get('user'):
- username = kwargs['user'].username
+def username(strategy, user=None, *args, **kwargs):
+ if user:
+ username = user.username
else:
- username = request.session.get('saved_username')
+ username = strategy.session_get('saved_username')
return {'username': username}
-def redirect_to_form2(*args, **kwargs):
- if not kwargs['request'].session.get('saved_first_name'):
+def redirect_to_form2(strategy, *args, **kwargs):
+ if strategy.session_get('saved_first_name'):
return HttpResponseRedirect('/form2/')
-def first_name(request, *args, **kwargs):
- if 'saved_first_name' in request.session:
+def first_name(strategy, *args, **kwargs):
+ if strategy.session_get('saved_first_name'):
user = kwargs['user']
- user.first_name = request.session.get('saved_first_name')
+ user.first_name = strategy.session_get('saved_first_name')
user.save()
View
7 example/app/views.py
@@ -6,7 +6,6 @@
from django.contrib.messages.api import get_messages
from social_auth import __version__ as version
-from social_auth.utils import setting
def home(request):
@@ -44,9 +43,8 @@ def logout(request):
def form(request):
if request.method == 'POST' and request.POST.get('username'):
- name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
request.session['saved_username'] = request.POST['username']
- backend = request.session[name]['backend']
+ backend = request.session['partial_pipeline']['backend']
return redirect('socialauth_complete', backend=backend)
return render_to_response('form.html', {}, RequestContext(request))
@@ -54,8 +52,7 @@ def form(request):
def form2(request):
if request.method == 'POST' and request.POST.get('first_name'):
request.session['saved_first_name'] = request.POST['first_name']
- name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
- backend = request.session[name]['backend']
+ backend = request.session['partial_pipeline']['backend']
return redirect('socialauth_complete', backend=backend)
return render_to_response('form2.html', {}, RequestContext(request))
View
47 example/app/vkontakte.py
@@ -9,11 +9,15 @@
from social_auth.models import UserSocialAuth
from social_auth.views import complete as social_complete
-from social_auth.utils import setting
-from social_auth.backends.contrib.vk import VKOAuth2Backend, vk_api
+from social_auth.backends.contrib.vk import VKOAuth2Backend
+
def is_complete_authentication(request):
- return request.user.is_authenticated() and VKOAuth2Backend.__name__ in request.session.get(BACKEND_SESSION_KEY, '')
+ return request.user.is_authenticated() and \
+ VKOAuth2Backend.__name__ in request.session.get(
+ BACKEND_SESSION_KEY, ''
+ )
+
def get_access_token(user):
key = str(user.id)
@@ -23,7 +27,10 @@ def get_access_token(user):
if access_token is None:
try:
social_user = user.social_user if hasattr(user, 'social_user') \
- else UserSocialAuth.objects.get(user=user.id, provider=VKOAuth2Backend.name)
+ else UserSocialAuth.objects.get(
+ user=user.id,
+ provider=VKOAuth2Backend.name
+ )
except UserSocialAuth.DoesNotExist:
return None
@@ -31,27 +38,29 @@ def get_access_token(user):
access_token = social_user.extra_data.get('access_token')
expires = social_user.extra_data.get('expires')
- cache.set(key, access_token, int(expires) if expires is not None else 0)
-
+ cache.set(key, access_token, int(expires) if expires is not None
+ else 0)
return access_token
+
# VK decorator to setup environment
def vkontakte_decorator(func):
def wrapper(request, *args, **kwargs):
user = request.user
- # User must me logged via VKontakte backend in order to ensure we talk about the same person
+ # User must me logged via VKontakte backend in order to ensure we talk
+ # about the same person
if not is_complete_authentication(request):
try:
user = social_complete(request, VKOAuth2Backend.name)
except (ValueError, AttributeError):
- pass # no matter if failed
+ pass # no matter if failed
- # Not recommended way for VK, but still something we need to be aware of
+ # Not recommended way for VK, but still something we need to be aware
+ # of
if isinstance(user, HttpResponse):
kwargs.update({'auth_response': user})
- # Need to re-check the completion
- else:
+ else: # Need to re-check the completion
if is_complete_authentication(request):
kwargs.update({'access_token': get_access_token(request.user)})
else:
@@ -61,18 +70,20 @@ def wrapper(request, *args, **kwargs):
return wrapper
+
@vkontakte_decorator
def vkontakte_view(request, *args, **kwargs):
- # If there is a ready response just return it. Not recommended because pipeline redirects fail the normal workflow
- # here.
+ # If there is a ready response just return it. Not recommended because
+ # pipeline redirects fail the normal workflow here.
auth_response = kwargs.get('auth_response')
if auth_response:
for item in auth_response.items():
if item[0] == 'Location' and 'form' in item[1]:
return auth_response
- return render_to_response('vkontakte_app.html',
- {'vk_app_id': settings.VKONTAKTE_APP_AUTH['id'] if hasattr(settings, 'VKONTAKTE_APP_AUTH') else None,
- 'app_scope': ','.join(settings.VKONTAKTE_OAUTH2_EXTRA_SCOPE),
- 'warning': not request.GET.get('user_id')},
- RequestContext(request))
+ return render_to_response('vkontakte_app.html', {
+ 'vk_app_id': settings.VKONTAKTE_APP_AUTH['id']
+ if hasattr(settings, 'VKONTAKTE_APP_AUTH') else None,
+ 'app_scope': ','.join(settings.VKONTAKTE_OAUTH2_EXTRA_SCOPE),
+ 'warning': not request.GET.get('user_id')
+ }, RequestContext(request))
View
40 example/example/settings.py
@@ -1,11 +1,16 @@
+import sys
from os.path import abspath, dirname, basename, join
-try:
- import social_auth
-except ImportError:
- import sys
- sys.path.insert(0, '..')
+#try:
+ #import social_auth
+ #social_auth # pyflakes
+#except ImportError:
+ #import sys
+# sys.path.insert(0, '..')
+
+sys.path.insert(0, '..')
+sys.path.insert(0, '../../python-social-auth')
DEBUG = True
@@ -44,7 +49,7 @@
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
-# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+ # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
SECRET_KEY = '_u6ym67ywnj0ugi2=6f-a_361i6o5elx91hftz$+klw)(*pqjw'
@@ -52,7 +57,7 @@
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
-# 'django.template.loaders.eggs.Loader',
+ # 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
@@ -82,6 +87,7 @@
'django.contrib.staticfiles',
'django.contrib.admin',
'south',
+ # 'social.apps.django_app.default',
'social_auth',
'app',
)
@@ -111,6 +117,7 @@
}
AUTHENTICATION_BACKENDS = (
+ 'social_auth.backends.OpenIDBackend',
'social_auth.backends.twitter.TwitterBackend',
'social_auth.backends.facebook.FacebookBackend',
'social_auth.backends.google.GoogleOAuthBackend',
@@ -118,37 +125,36 @@
'social_auth.backends.google.GoogleBackend',
'social_auth.backends.yahoo.YahooBackend',
'social_auth.backends.stripe.StripeBackend',
+ 'social_auth.backends.steam.SteamBackend',
+ 'social_auth.backends.reddit.RedditBackend',
+ 'social_auth.backends.amazon.AmazonBackend',
+ 'social_auth.backends.browserid.BrowserIDBackend',
'social_auth.backends.contrib.linkedin.LinkedinBackend',
'social_auth.backends.contrib.skyrock.SkyrockBackend',
'social_auth.backends.contrib.flickr.FlickrBackend',
'social_auth.backends.contrib.instagram.InstagramBackend',
'social_auth.backends.contrib.github.GithubBackend',
'social_auth.backends.contrib.yandex.YandexBackend',
+ 'social_auth.backends.contrib.yandex.YandexOAuth2Backend',
+ 'social_auth.backends.contrib.yandex.YaruBackend',
'social_auth.backends.contrib.disqus.DisqusBackend',
'social_auth.backends.contrib.yahoo.YahooOAuthBackend',
'social_auth.backends.contrib.foursquare.FoursquareBackend',
- 'social_auth.backends.OpenIDBackend',
'social_auth.backends.contrib.live.LiveBackend',
'social_auth.backends.contrib.livejournal.LiveJournalBackend',
'social_auth.backends.contrib.douban.DoubanBackend',
- 'social_auth.backends.browserid.BrowserIDBackend',
'social_auth.backends.contrib.vk.VKOpenAPIBackend',
- 'social_auth.backends.contrib.yandex.YandexOAuth2Backend',
- 'social_auth.backends.contrib.yandex.YaruBackend',
+ 'social_auth.backends.contrib.vk.VKOAuth2Backend',
'social_auth.backends.contrib.odnoklassniki.OdnoklassnikiBackend',
'social_auth.backends.contrib.odnoklassniki.OdnoklassnikiAppBackend',
- 'social_auth.backends.contrib.vk.VKOAuth2Backend',
'social_auth.backends.contrib.mailru.MailruBackend',
'social_auth.backends.contrib.dailymotion.DailymotionBackend',
- 'social_auth.backends.contrib.shopify.ShopifyBackend',
- 'social_auth.backends.contrib.exacttarget.ExactTargetBackend',
+ # 'social_auth.backends.contrib.shopify.ShopifyBackend',
+ # 'social_auth.backends.contrib.exacttarget.ExactTargetBackend',
'social_auth.backends.contrib.stocktwits.StocktwitsBackend',
'social_auth.backends.contrib.behance.BehanceBackend',
'social_auth.backends.contrib.readability.ReadabilityBackend',
'social_auth.backends.contrib.fedora.FedoraBackend',
- 'social_auth.backends.steam.SteamBackend',
- 'social_auth.backends.reddit.RedditBackend',
- 'social_auth.backends.amazon.AmazonBackend',
'django.contrib.auth.backends.ModelBackend',
)
View
5 requirements.txt
@@ -1,5 +1,2 @@
django>=1.2.5
-oauth2>=1.5.167
-python_openid>=2.2
-selenium>=2.29.0
-mock==1.0.1
+python-social-auth>=0.1.10
View
3  setup.py
@@ -45,8 +45,7 @@ def long_description():
package_data={'social_auth': ['locale/*/LC_MESSAGES/*']},
long_description=long_description(),
install_requires=['Django>=1.2.5',
- 'oauth2>=1.5.167',
- 'python-openid>=2.2'],
+ 'python-social-auth>=0.1.10'],
classifiers=['Framework :: Django',
'Development Status :: 4 - Beta',
'Topic :: Internet',
View
10 social_auth/__init__.py
@@ -2,5 +2,13 @@
Django-social-auth application, allows OpenId or OAuth user
registration/authentication just adding a few configurations.
"""
-version = (0, 7, 28)
+from django.conf import settings
+
+
+version = (0, 8, 0)
__version__ = '.'.join(map(str, version))
+
+
+MODELS = getattr(settings, 'SOCIAL_AUTH_MODELS',
+ 'social_auth.db.django_models')
+IS_DJANGO_MODELS = MODELS == 'social_auth.db.django_models'
View
46 social_auth/admin.py
@@ -1,44 +1,6 @@
-"""Admin settings"""
-from social_auth.utils import setting
+from social_auth import IS_DJANGO_MODELS
-if setting('SOCIAL_AUTH_MODELS') in (None, 'social_auth.db.django_models'):
- from django.contrib import admin
- from social_auth.models import UserSocialAuth, Nonce, Association
-
- _User = UserSocialAuth.user_model()
-
- if hasattr(_User, 'USERNAME_FIELD'):
- username_field = _User.USERNAME_FIELD
- elif hasattr(_User, 'username'):
- username_field = 'username'
- else:
- username_field = None
-
- fieldnames = ('first_name', 'last_name', 'email') + (username_field,)
- all_names = _User._meta.get_all_field_names()
- user_search_fields = ['user__' + name for name in fieldnames
- if name in all_names]
-
- class UserSocialAuthOption(admin.ModelAdmin):
- """Social Auth user options"""
- list_display = ('id', 'user', 'provider', 'uid')
- search_fields = user_search_fields
- list_filter = ('provider',)
- raw_id_fields = ('user',)
- list_select_related = True
-
- class NonceOption(admin.ModelAdmin):
- """Nonce options"""
- list_display = ('id', 'server_url', 'timestamp', 'salt')
- search_fields = ('server_url',)
-
- class AssociationOption(admin.ModelAdmin):
- """Association options"""
- list_display = ('id', 'server_url', 'assoc_type')
- list_filter = ('assoc_type',)
- search_fields = ('server_url',)
-
- admin.site.register(UserSocialAuth, UserSocialAuthOption)
- admin.site.register(Nonce, NonceOption)
- admin.site.register(Association, AssociationOption)
+if IS_DJANGO_MODELS:
+ from social.apps.django_app.default import admin
+ admin # placate pyflakes
View
1,004 social_auth/backends/__init__.py
@@ -1,1002 +1,14 @@
-"""
-Base backends structures.
+from django.conf import settings
-This module defines base classes needed to define custom OpenID or OAuth
-auth services from third parties. This customs must subclass an Auth and
-and Backend class, check current implementation for examples.
-
-Also the modules *must* define a BACKENDS dictionary with the backend name
-(which is used for URLs matching) and Auth class, otherwise it won't be
-enabled.
-"""
-from urllib2 import Request, HTTPError
-from urllib import urlencode
-
-from openid.consumer.consumer import Consumer, SUCCESS, CANCEL, FAILURE
-from openid.consumer.discover import DiscoveryFailure
-from openid.extensions import sreg, ax, pape
-
-from oauth2 import Consumer as OAuthConsumer, Token, Request as OAuthRequest
-
-try:
- import json as simplejson
-except ImportError:
- try:
- import simplejson
- except ImportError:
- from django.utils import simplejson
-
-from django.contrib.auth import authenticate
-from django.utils.importlib import import_module
-
-from social_auth.models import UserSocialAuth
-from social_auth.utils import setting, model_to_ctype, ctype_to_model, \
- clean_partial_pipeline, url_add_parameters, \
- get_random_string, constant_time_compare, \
- dsa_urlopen
-from social_auth.store import DjangoOpenIDStore
-from social_auth.exceptions import StopPipeline, AuthException, AuthFailed, \
- AuthCanceled, AuthUnknownError, \
- AuthTokenError, AuthMissingParameter, \
- AuthStateMissing, AuthStateForbidden, \
- NotAllowedToDisconnect, BackendError
-from social_auth.backends.utils import build_consumer_oauth_request
-
-
-# OpenID configuration
-OLD_AX_ATTRS = [
- ('http://schema.openid.net/contact/email', 'old_email'),
- ('http://schema.openid.net/namePerson', 'old_fullname'),
- ('http://schema.openid.net/namePerson/friendly', 'old_nickname')
-]
-AX_SCHEMA_ATTRS = [
- # Request both the full name and first/last components since some
- # providers offer one but not the other.
- ('http://axschema.org/contact/email', 'email'),
- ('http://axschema.org/namePerson', 'fullname'),
- ('http://axschema.org/namePerson/first', 'first_name'),
- ('http://axschema.org/namePerson/last', 'last_name'),
- ('http://axschema.org/namePerson/friendly', 'nickname'),
-]
-SREG_ATTR = [
- ('email', 'email'),
- ('fullname', 'fullname'),
- ('nickname', 'nickname')
-]
-OPENID_ID_FIELD = 'openid_identifier'
-SESSION_NAME = 'openid'
-
-PIPELINE = setting('SOCIAL_AUTH_PIPELINE', (
- 'social_auth.backends.pipeline.social.social_auth_user',
- # Removed by default since it can be a dangerouse behavior that
- # could lead to accounts take over.
- #'social_auth.backends.pipeline.associate.associate_by_email',
- 'social_auth.backends.pipeline.user.get_username',
- 'social_auth.backends.pipeline.user.create_user',
- 'social_auth.backends.pipeline.social.associate_user',
- 'social_auth.backends.pipeline.social.load_extra_data',
- 'social_auth.backends.pipeline.user.update_user_details',
- ))
-
-
-class SocialAuthBackend(object):
- """A django.contrib.auth backend that authenticates the user based on
- a authentication provider response"""
- name = '' # provider name, it's stored in database
- supports_inactive_user = False
-
- def authenticate(self, *args, **kwargs):
- """Authenticate user using social credentials
-
- Authentication is made if this is the correct backend, backend
- verification is made by kwargs inspection for current backend
- name presence.
- """
- # Validate backend and arguments. Require that the Social Auth
- # response be passed in as a keyword argument, to make sure we
- # don't match the username/password calling conventions of
- # authenticate.
- if not (self.name and kwargs.get(self.name) and 'response' in kwargs):
- return None
-
- response = kwargs.get('response')
- pipeline = PIPELINE
- kwargs = kwargs.copy()
- kwargs['backend'] = self
-
- if 'pipeline_index' in kwargs:
- pipeline = pipeline[kwargs['pipeline_index']:]
- else:
- kwargs['details'] = self.get_user_details(response)
- kwargs['uid'] = self.get_user_id(kwargs['details'], response)
- kwargs['is_new'] = False
-
- out = self.pipeline(pipeline, *args, **kwargs)
- if not isinstance(out, dict):
- return out
-
- social_user = out.get('social_user')
- if social_user:
- # define user.social_user attribute to track current social
- # account
- user = social_user.user
- user.social_user = social_user
- user.is_new = out.get('is_new')
- return user
-
- def pipeline(self, pipeline, *args, **kwargs):
- """Pipeline"""
- out = kwargs.copy()
-
- if 'pipeline_index' in kwargs:
- base_index = int(kwargs['pipeline_index'])
- else:
- base_index = 0
-
- for idx, name in enumerate(pipeline):
- out['pipeline_index'] = base_index + idx
- mod_name, func_name = name.rsplit('.', 1)
- mod = import_module(mod_name)
- func = getattr(mod, func_name, None)
-
- try:
- result = func(*args, **out) or {}
- except StopPipeline:
- # Clean partial pipeline on stop
- if 'request' in kwargs:
- clean_partial_pipeline(kwargs['request'])
- break
-
- if isinstance(result, dict):
- out.update(result)
- else:
- return result
-
- # clean the partial pipeline at the end of the process
- if 'request' in kwargs:
- clean_partial_pipeline(kwargs['request'])
- return out
-
- def extra_data(self, user, uid, response, details):
- """Return default blank user extra data"""
- return {}
-
- def get_user_id(self, details, response):
- """Must return a unique ID from values returned on details"""
- raise NotImplementedError('Implement in subclass')
-
- def get_user_details(self, response):
- """Must return user details in a know internal struct:
- {'username': <username if any>,
- 'email': <user email if any>,
- 'fullname': <user full name if any>,
- 'first_name': <user first name if any>,
- 'last_name': <user last name if any>}
- """
- raise NotImplementedError('Implement in subclass')
-
- @classmethod
- def tokens(cls, instance):
- """Return the tokens needed to authenticate the access to any API the
- service might provide. The return value will be a dictionary with the
- token type name as key and the token value.
-
- instance must be a UserSocialAuth instance.
- """
- if instance.extra_data and 'access_token' in instance.extra_data:
- return {
- 'access_token': instance.extra_data['access_token']
- }
- else:
- return {}
-
- def get_user(self, user_id):
- """
- Return user with given ID from the User model used by this backend.
- This is called by django.contrib.auth.middleware.
- """
- return UserSocialAuth.get_user(user_id)
-
-
-class OAuthBackend(SocialAuthBackend):
- """OAuth authentication backend base class.
-
- EXTRA_DATA defines a set of name that will be stored in
- extra_data field. It must be a list of tuples with
- name and alias.
-
- Also settings will be inspected to get more values names that should be
- stored on extra_data field. Setting name is created from current backend
- name (all uppercase) plus _EXTRA_DATA.
-
- access_token is always stored.
- """
- EXTRA_DATA = None
- ID_KEY = 'id'
-
- def get_user_id(self, details, response):
- """OAuth providers return an unique user id in response"""
- return response[self.ID_KEY]
-
- @classmethod
- def extra_data(cls, user, uid, response, details=None):
- """Return access_token and extra defined names to store in
- extra_data field"""
- data = {'access_token': response.get('access_token', '')}
- name = cls.name.replace('-', '_').upper()
- names = (cls.EXTRA_DATA or []) + setting(name + '_EXTRA_DATA', [])
-
- for entry in names:
- if type(entry) is str:
- entry = (entry,)
-
- try:
- if len(entry) == 3:
- name, alias, discard = entry
- elif len(entry) == 2:
- (name, alias), discard = entry, False
- elif len(entry) == 1:
- (name,), (alias,), discard = entry, entry, False
- else:
- raise ValueError('invalid tuple for EXTRA_DATA entry' % entry)
-
- value = response.get(name)
- if discard and not value:
- continue
- data[alias] = value
-
- except (TypeError, ValueError), e:
- raise BackendError('invalid entry: %s' % (entry,))
-
- return data
-
-class OpenIDBackend(SocialAuthBackend):
- """Generic OpenID authentication backend"""
- name = 'openid'
-
- def get_user_id(self, details, response):
- """Return user unique id provided by service"""
- return response.identity_url
-
- def values_from_response(self, response, sreg_names=None, ax_names=None):
- """Return values from SimpleRegistration response or
- AttributeExchange response if present.
-
- @sreg_names and @ax_names must be a list of name and aliases
- for such name. The alias will be used as mapping key.
- """
- values = {}
-
- # Use Simple Registration attributes if provided
- if sreg_names:
- resp = sreg.SRegResponse.fromSuccessResponse(response)
- if resp:
- values.update((alias, resp.get(name) or '')
- for name, alias in sreg_names)
-
- # Use Attribute Exchange attributes if provided
- if ax_names:
- resp = ax.FetchResponse.fromSuccessResponse(response)
- if resp:
- for src, alias in ax_names:
- name = alias.replace('old_', '')
- values[name] = resp.getSingle(src, '') or values.get(name)
- return values
-
- def get_user_details(self, response):
- """Return user details from an OpenID request"""
- values = {'username': '', 'email': '', 'fullname': '',
- 'first_name': '', 'last_name': ''}
- # update values using SimpleRegistration or AttributeExchange
- # values
- values.update(self.values_from_response(response,
- SREG_ATTR,
- OLD_AX_ATTRS +
- AX_SCHEMA_ATTRS))
-
- fullname = values.get('fullname') or ''
- first_name = values.get('first_name') or ''
- last_name = values.get('last_name') or ''
-
- if not fullname and first_name and last_name:
- fullname = first_name + ' ' + last_name
- elif fullname:
- try: # Try to split name for django user storage
- first_name, last_name = fullname.rsplit(' ', 1)
- except ValueError:
- last_name = fullname
-
- values.update({
- 'fullname': fullname,
- 'first_name': first_name,
- 'last_name': last_name,
- 'username': values.get('username') or
- (first_name.title() + last_name.title())
- })
- return values
-
- def extra_data(self, user, uid, response, details):
- """Return defined extra data names to store in extra_data field.
- Settings will be inspected to get more values names that should be
- stored on extra_data field. Setting name is created from current
- backend name (all uppercase) plus _SREG_EXTRA_DATA and
- _AX_EXTRA_DATA because values can be returned by SimpleRegistration
- or AttributeExchange schemas.
-
- Both list must be a value name and an alias mapping similar to
- SREG_ATTR, OLD_AX_ATTRS or AX_SCHEMA_ATTRS
- """
- name = self.name.replace('-', '_').upper()
- sreg_names = setting(name + '_SREG_EXTRA_DATA')
- ax_names = setting(name + '_AX_EXTRA_DATA')
- data = self.values_from_response(response, sreg_names, ax_names)
- return data
-
-
-class BaseAuth(object):
- """Base authentication class, new authenticators should subclass
- and implement needed methods.
-
- AUTH_BACKEND Authorization backend related with this service
- """
- AUTH_BACKEND = None
-
- def __init__(self, request, redirect):
- self.request = request
- # Use request because some auth providers use POST urls with needed
- # GET parameters on it
- self.data = request.REQUEST
- self.redirect = redirect
-
- def auth_url(self):
- """Must return redirect URL to auth provider"""
- raise NotImplementedError('Implement in subclass')
-
- def auth_html(self):
- """Must return login HTML content returned by provider"""
- raise NotImplementedError('Implement in subclass')
-
- def auth_complete(self, *args, **kwargs):
- """Completes loging process, must return user instance"""
- raise NotImplementedError('Implement in subclass')
-
- def to_session_dict(self, next_idx, *args, **kwargs):
- """Returns dict to store on session for partial pipeline."""
- return {
- 'next': next_idx,
- 'backend': self.AUTH_BACKEND.name,
- 'args': tuple(map(model_to_ctype, args)),
- 'kwargs': dict((key, model_to_ctype(val))
- for key, val in kwargs.iteritems())
- }
-
- def from_session_dict(self, session_data, *args, **kwargs):
- """Takes session saved data to continue pipeline and merges with any
- new extra argument needed. Returns tuple with next pipeline index
- entry, arguments and keyword arguments to continue the process."""
- args = args[:] + tuple(map(ctype_to_model, session_data['args']))
-
- kwargs = kwargs.copy()
- saved_kwargs = dict((key, ctype_to_model(val))
- for key, val in session_data['kwargs'].iteritems())
- saved_kwargs.update((key, val)
- for key, val in kwargs.iteritems())
- return (session_data['next'], args, saved_kwargs)
-
- def continue_pipeline(self, *args, **kwargs):
- """Continue previous halted pipeline"""
- kwargs.update({
- 'auth': self,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
-
- def request_token_extra_arguments(self):
- """Return extra arguments needed on request-token process,
- setting is per backend and defined by:
- <backend name in uppercase>_REQUEST_TOKEN_EXTRA_ARGUMENTS.
- """
- backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_')
- return setting(backend_name + '_REQUEST_TOKEN_EXTRA_ARGUMENTS', {})
-
- def auth_extra_arguments(self):
- """Return extra arguments needed on auth process, setting is per
- backend and defined by:
- <backend name in uppercase>_AUTH_EXTRA_ARGUMENTS.
- The defaults can be overriden by GET parameters.
- """
- backend_name = self.AUTH_BACKEND.name.upper().replace('-', '_')
- extra_arguments = setting(backend_name + '_AUTH_EXTRA_ARGUMENTS', {})
- for key, value in extra_arguments.iteritems():
- if key in self.data:
- extra_arguments[key] = self.data[key]
- elif value:
- extra_arguments[key] = value
- return extra_arguments
-
- @property
- def uses_redirect(self):
- """Return True if this provider uses redirect url method,
- otherwise return false."""
- return True
-
- @classmethod
- def enabled(cls):
- """Return backend enabled status, all enabled by default"""
- return True
-
- def disconnect(self, user, association_id=None):
- """Deletes current backend from user if associated.
- Override if extra operations are needed.
- """
- name = self.AUTH_BACKEND.name
- if UserSocialAuth.allowed_to_disconnect(user, name, association_id):
- do_revoke = setting('SOCIAL_AUTH_REVOKE_TOKENS_ON_DISCONNECT')
- filter_args = {}
-
- if association_id:
- filter_args['id'] = association_id
- else:
- filter_args['provider'] = name
- instances = UserSocialAuth.get_social_auth_for_user(user)\
- .filter(**filter_args)
-
- if do_revoke:
- for instance in instances:
- instance.revoke_token(drop_token=False)
- instances.delete()
- else:
- raise NotAllowedToDisconnect()
-
- def build_absolute_uri(self, path=None):
- """Build absolute URI for given path. Replace http:// schema with
- https:// if SOCIAL_AUTH_REDIRECT_IS_HTTPS is defined.
- """
- uri = self.request.build_absolute_uri(path)
- if setting('SOCIAL_AUTH_REDIRECT_IS_HTTPS'):
- uri = uri.replace('http://', 'https://')
- return uri
-
-
-class OpenIdAuth(BaseAuth):
- """OpenId process handling"""
- AUTH_BACKEND = OpenIDBackend
-
- def auth_url(self):
- """Return auth URL returned by service"""
- openid_request = self.setup_request(self.auth_extra_arguments())
- # Construct completion URL, including page we should redirect to
- return_to = self.build_absolute_uri(self.redirect)
- return openid_request.redirectURL(self.trust_root(), return_to)
-
- def auth_html(self):
- """Return auth HTML returned by service"""
- openid_request = self.setup_request(self.auth_extra_arguments())
- return_to = self.build_absolute_uri(self.redirect)
- form_tag = {'id': 'openid_message'}
- return openid_request.htmlMarkup(self.trust_root(), return_to,
- form_tag_attrs=form_tag)
-
- def trust_root(self):
- """Return trust-root option"""
- return setting('OPENID_TRUST_ROOT') or self.build_absolute_uri('/')
-
- def continue_pipeline(self, *args, **kwargs):
- """Continue previous halted pipeline"""
- response = self.consumer().complete(dict(self.data.items()),
- self.build_absolute_uri())
- kwargs.update({
- 'auth': self,
- 'response': response,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
-
- def auth_complete(self, *args, **kwargs):
- """Complete auth process"""
- response = self.consumer().complete(dict(self.data.items()),
- self.build_absolute_uri())
- if not response:
- raise AuthException(self, 'OpenID relying party endpoint')
- elif response.status == SUCCESS:
- kwargs.update({
- 'auth': self,
- 'response': response,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
- elif response.status == FAILURE:
- raise AuthFailed(self, response.message)
- elif response.status == CANCEL:
- raise AuthCanceled(self)
- else:
- raise AuthUnknownError(self, response.status)
-
- def setup_request(self, extra_params=None):
- """Setup request"""
- openid_request = self.openid_request(extra_params)
- # Request some user details. Use attribute exchange if provider
- # advertises support.
- if openid_request.endpoint.supportsType(ax.AXMessage.ns_uri):
- fetch_request = ax.FetchRequest()
- # Mark all attributes as required, Google ignores optional ones
- for attr, alias in (AX_SCHEMA_ATTRS + OLD_AX_ATTRS):
- fetch_request.add(ax.AttrInfo(attr, alias=alias,
- required=True))
- else:
- fetch_request = sreg.SRegRequest(optional=dict(SREG_ATTR).keys())
- openid_request.addExtension(fetch_request)
-
- # Add PAPE Extension for if configured
- preferred_policies = setting(
- 'SOCIAL_AUTH_OPENID_PAPE_PREFERRED_AUTH_POLICIES')
- preferred_level_types = setting(
- 'SOCIAL_AUTH_OPENID_PAPE_PREFERRED_AUTH_LEVEL_TYPES')
- max_age = setting('SOCIAL_AUTH_OPENID_PAPE_MAX_AUTH_AGE')
- if max_age is not None:
- try:
- max_age = int(max_age)
- except (ValueError, TypeError):
- max_age = None
-
- if (max_age is not None or preferred_policies is not None
- or preferred_level_types is not None):
- pape_request = pape.Request(
- preferred_auth_policies=preferred_policies,
- max_auth_age=max_age,
- preferred_auth_level_types=preferred_level_types
- )
- openid_request.addExtension(pape_request)
-
- return openid_request
-
- def consumer(self):
- """Create an OpenID Consumer object for the given Django request."""
- return Consumer(self.request.session.setdefault(SESSION_NAME, {}),
- DjangoOpenIDStore())
-
- @property
- def uses_redirect(self):
- """Return true if openid request will be handled with redirect or
- HTML content will be returned.
- """
- return self.openid_request(self.auth_extra_arguments())\
- .shouldSendRedirect()
-
- def openid_request(self, extra_params=None):
- """Return openid request"""
- if not hasattr(self, '_openid_request'):
- try:
- self._openid_request = self.consumer().begin(
- url_add_parameters(self.openid_url(), extra_params)
- )
- except DiscoveryFailure, err:
- raise AuthException(self, 'OpenID discovery error: %s' % err)
- return self._openid_request
-
- def openid_url(self):
- """Return service provider URL.
- This base class is generic accepting a POST parameter that specifies
- provider URL."""
- if OPENID_ID_FIELD not in self.data:
- raise AuthMissingParameter(self, OPENID_ID_FIELD)
- return self.data[OPENID_ID_FIELD]
-
-
-class BaseOAuth(BaseAuth):
- """OAuth base class"""
- SETTINGS_KEY_NAME = ''
- SETTINGS_SECRET_NAME = ''
- SCOPE_VAR_NAME = None
- SCOPE_PARAMETER_NAME = 'scope'
- DEFAULT_SCOPE = None
- SCOPE_SEPARATOR = ' '
-
- def __init__(self, request, redirect):
- """Init method"""
- super(BaseOAuth, self).__init__(request, redirect)
- self.redirect_uri = self.build_absolute_uri(self.redirect)
-
- @classmethod
- def get_key_and_secret(cls):
- """Return tuple with Consumer Key and Consumer Secret for current
- service provider. Must return (key, secret), order *must* be respected.
- """
- return setting(cls.SETTINGS_KEY_NAME), \
- setting(cls.SETTINGS_SECRET_NAME)
-
- @classmethod
- def enabled(cls):
- """Return backend enabled status by checking basic settings"""
- return setting(cls.SETTINGS_KEY_NAME) and \
- setting(cls.SETTINGS_SECRET_NAME)
-
- def get_scope(self):
- """Return list with needed access scope"""
- scope = self.DEFAULT_SCOPE or []
- if self.SCOPE_VAR_NAME:
- scope = scope + setting(self.SCOPE_VAR_NAME, [])
- return scope
-
- def get_scope_argument(self):
- param = {}
- scope = self.get_scope()
- if scope:
- param[self.SCOPE_PARAMETER_NAME] = self.SCOPE_SEPARATOR.join(scope)
- return param
-
- def user_data(self, access_token, *args, **kwargs):
- """Loads user data from service. Implement in subclass"""
- return {}
-
-
-class ConsumerBasedOAuth(BaseOAuth):
- """Consumer based mechanism OAuth authentication, fill the needed
- parameters to communicate properly with authentication service.
-
- AUTHORIZATION_URL Authorization service url
- REQUEST_TOKEN_URL Request token URL
- ACCESS_TOKEN_URL Access token URL
- """
- AUTHORIZATION_URL = ''
- REQUEST_TOKEN_URL = ''
- ACCESS_TOKEN_URL = ''
-
- def auth_url(self):
- """Return redirect url"""
- token = self.unauthorized_token()
- name = self.AUTH_BACKEND.name + 'unauthorized_token_name'
- if not isinstance(self.request.session.get(name), list):
- self.request.session[name] = []
- self.request.session[name].append(token.to_string())
- self.request.session.modified = True
- return self.oauth_authorization_request(token).to_url()
-
- def auth_complete(self, *args, **kwargs):
- """Return user, might be logged in"""
- # Multiple unauthorized tokens are supported (see #521)
- name = self.AUTH_BACKEND.name + 'unauthorized_token_name'
- token = None
- unauthed_tokens = self.request.session.get(name) or []
- if not unauthed_tokens:
- raise AuthTokenError(self, 'Missing unauthorized token')
- for unauthed_token in unauthed_tokens:
- token = Token.from_string(unauthed_token)
- if token.key == self.data.get('oauth_token', 'no-token'):
- unauthed_tokens = list(set(unauthed_tokens) -
- set([unauthed_token]))
- self.request.session[name] = unauthed_tokens
- self.request.session.modified = True
- break
- else:
- raise AuthTokenError(self, 'Incorrect tokens')
-
- try:
- access_token = self.access_token(token)
- except HTTPError, e:
- if e.code == 400:
- raise AuthCanceled(self)
- else:
- raise
- return self.do_auth(access_token, *args, **kwargs)
-
- def do_auth(self, access_token, *args, **kwargs):
- """Finish the auth process once the access_token was retrieved"""
- if isinstance(access_token, basestring):
- access_token = Token.from_string(access_token)
-
- data = self.user_data(access_token)
- if data is not None:
- data['access_token'] = access_token.to_string()
-
- kwargs.update({
- 'auth': self,
- 'response': data,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
-
- def unauthorized_token(self):
- """Return request for unauthorized token (first stage)"""
- request = self.oauth_request(
- token=None,
- url=self.REQUEST_TOKEN_URL,
- extra_params=self.request_token_extra_arguments()
- )
- return Token.from_string(self.fetch_response(request))
-
- def oauth_authorization_request(self, token):
- """Generate OAuth request to authorize token."""
- params = self.auth_extra_arguments() or {}
- params.update(self.get_scope_argument())
- return OAuthRequest.from_token_and_callback(
- token=token,
- callback=self.redirect_uri,
- http_url=self.AUTHORIZATION_URL,
- parameters=params
- )
-
- def oauth_request(self, token, url, extra_params=None):
- """Generate OAuth request, setups callback url"""
- return build_consumer_oauth_request(self, token, url,
- self.redirect_uri,
- self.data.get('oauth_verifier'),
- extra_params)
-
- def fetch_response(self, request):
- """Executes request and fetchs service response"""
- response = dsa_urlopen(request.to_url())
- return '\n'.join(response.readlines())
-
- def access_token(self, token):
- """Return request for access token value"""
- request = self.oauth_request(token, self.ACCESS_TOKEN_URL)
- return Token.from_string(self.fetch_response(request))
-
- @property
- def consumer(self):
- """Setups consumer"""
- return OAuthConsumer(*self.get_key_and_secret())
-
-
-class BaseOAuth2(BaseOAuth):
- """Base class for OAuth2 providers.
-
- OAuth2 draft details at:
- http://tools.ietf.org/html/draft-ietf-oauth-v2-10
-
- Attributes:
- AUTHORIZATION_URL Authorization service url
- ACCESS_TOKEN_URL Token URL
- """
- AUTHORIZATION_URL = None
- ACCESS_TOKEN_URL = None
- REFRESH_TOKEN_URL = None
- REVOKE_TOKEN_URL = None
- REVOKE_TOKEN_METHOD = 'POST'
- RESPONSE_TYPE = 'code'
- REDIRECT_STATE = True
- STATE_PARAMETER = True
-
- def state_token(self):
- """Generate csrf token to include as state parameter."""
- return get_random_string(32)
-
- def get_redirect_uri(self, state=None):
- """Build redirect_uri with redirect_state parameter."""
- uri = self.redirect_uri
- if self.REDIRECT_STATE and state:
- uri = url_add_parameters(uri, {'redirect_state': state})
- return uri
-
- def auth_params(self, state=None):
- client_id, client_secret = self.get_key_and_secret()
- params = {
- 'client_id': client_id,
- 'redirect_uri': self.get_redirect_uri(state)
- }
- if self.STATE_PARAMETER and state:
- params['state'] = state
- if self.RESPONSE_TYPE:
- params['response_type'] = self.RESPONSE_TYPE
- return params
-
- def auth_url(self):
- """Return redirect url"""
- if self.STATE_PARAMETER or self.REDIRECT_STATE:
- # Store state in session for further request validation. The state
- # value is passed as state parameter (as specified in OAuth2 spec),
- # but also added to redirect_uri, that way we can still verify the
- # request if the provider doesn't implement the state parameter.
- # Reuse token if any.
- name = self.AUTH_BACKEND.name + '_state'
- state = self.request.session.get(name) or self.state_token()
- self.request.session[self.AUTH_BACKEND.name + '_state'] = state
- else:
- state = None
-
- params = self.auth_params(state)
- params.update(self.get_scope_argument())
- params.update(self.auth_extra_arguments())
-
- if self.request.META.get('QUERY_STRING'):
- query_string = '&' + self.request.META['QUERY_STRING']
- else:
- query_string = ''
- return self.AUTHORIZATION_URL + '?' + urlencode(params) + query_string
-
- def validate_state(self):
- """Validate state value. Raises exception on error, returns state
- value if valid."""
- if not self.STATE_PARAMETER and not self.REDIRECT_STATE:
- return None
- state = self.request.session.get(self.AUTH_BACKEND.name + '_state')
- if state:
- request_state = self.data.get('state') or \
- self.data.get('redirect_state')
- if not request_state:
- raise AuthMissingParameter(self, 'state')
- elif not state:
- raise AuthStateMissing(self, 'state')
- elif not constant_time_compare(request_state, state):
- raise AuthStateForbidden(self)
- return state
-
- def process_error(self, data):
- error = data.get('error_description') or data.get('error')
- if error:
- raise AuthFailed(self, error)
-
- def auth_complete_params(self, state=None):
- client_id, client_secret = self.get_key_and_secret()
- return {
- 'grant_type': 'authorization_code', # request auth code
- 'code': self.data.get('code', ''), # server response code
- 'client_id': client_id,
- 'client_secret': client_secret,
- 'redirect_uri': self.get_redirect_uri(state)
- }
-
- @classmethod
- def auth_headers(cls):
- return {'Content-Type': 'application/x-www-form-urlencoded',
- 'Accept': 'application/json'}
-
- def auth_complete(self, *args, **kwargs):
- """Completes loging process, must return user instance"""
- self.process_error(self.data)
- params = self.auth_complete_params(self.validate_state())
- request = Request(self.ACCESS_TOKEN_URL, data=urlencode(params),
- headers=self.auth_headers())
-
- try:
- response = simplejson.loads(dsa_urlopen(request).read())
- except HTTPError, e:
- if e.code == 400:
- raise AuthCanceled(self)
- else:
- raise
- except (ValueError, KeyError):
- raise AuthUnknownError(self)
-
- self.process_error(response)
- return self.do_auth(response['access_token'], response=response,
- *args, **kwargs)
-
- @classmethod
- def refresh_token_params(cls, token):
- client_id, client_secret = cls.get_key_and_secret()
- return {
- 'refresh_token': token,
- 'grant_type': 'refresh_token',
- 'client_id': client_id,
- 'client_secret': client_secret
- }
-
- @classmethod
- def process_refresh_token_response(cls, response):
- return simplejson.loads(response)
-
- @classmethod
- def refresh_token(cls, token):
- request = Request(
- cls.REFRESH_TOKEN_URL or cls.ACCESS_TOKEN_URL,
- data=urlencode(cls.refresh_token_params(token)),
- headers=cls.auth_headers()
- )
- return cls.process_refresh_token_response(dsa_urlopen(request).read())
-
- @classmethod
- def revoke_token_params(cls, token, uid):
- return None
-
- @classmethod
- def revoke_token_headers(cls, token, uid):
- return None
-
- @classmethod
- def process_revoke_token_response(cls, response):
- return response.code == 200
-
- @classmethod
- def revoke_token(cls, token, uid):
- if not cls.REVOKE_TOKEN_URL:
- return
- url = cls.REVOKE_TOKEN_URL.format(token=token, uid=uid)
- params = cls.revoke_token_params(token, uid) or {}
- headers = cls.revoke_token_headers(token, uid) or {}
- data = None
-
- if cls.REVOKE_TOKEN_METHOD == 'GET':
- url = '{}?{}'.format(url, urlencode(params))
- else:
- data = urlencode(params)
-
- request = Request(url, data=data, headers=headers)
- if cls.REVOKE_TOKEN_URL.lower() not in ('get', 'post'):
- # Patch get_method to return the needed method
- request.get_method = lambda: cls.REVOKE_TOKEN_METHOD
- response = dsa_urlopen(request)
- return cls.process_revoke_token_response(response)
-
- def do_auth(self, access_token, *args, **kwargs):
- """Finish the auth process once the access_token was retrieved"""
- data = self.user_data(access_token, *args, **kwargs)
- response = kwargs.get('response') or {}
- response.update(data or {})
- kwargs.update({
- 'auth': self,
- 'response': response,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
-
-
-# Backend loading was previously performed via the
-# SOCIAL_AUTH_IMPORT_BACKENDS setting - as it's no longer used,
-# provide a deprecation warning.
-if setting('SOCIAL_AUTH_IMPORT_BACKENDS'):
- from warnings import warn
- warn("SOCIAL_AUTH_IMPORT_SOURCES is deprecated")
-
-
-# Cache for discovered backends.
-BACKENDSCACHE = {}
+from social.backends.utils import load_backends, get_backend
+from social.backends.open_id import OpenIdAuth as OpenIDBackend
def get_backends(force_load=False):
- """
- Entry point to the BACKENDS cache. If BACKENDSCACHE hasn't been
- populated, each of the modules referenced in
- AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS
- definition and if enabled, added to the cache.
-
- Previously all backends were attempted to be loaded at
- import time of this module, which meant that backends that subclass
- bases found in this module would not have the chance to be loaded
- by the time they were added to this module's BACKENDS dict. See:
- https://github.com/omab/django-social-auth/issues/204
-
- This new approach ensures that backends are allowed to subclass from
- bases in this module and still be picked up.
-
- A force_load boolean arg is also provided so that get_backend
- below can retry a requested backend that may not yet be discovered.
- """
- if not BACKENDSCACHE or force_load:
- for auth_backend in setting('AUTHENTICATION_BACKENDS'):
- mod, cls_name = auth_backend.rsplit('.', 1)
- module = import_module(mod)
- backend = getattr(module, cls_name)
-
- if issubclass(backend, SocialAuthBackend):
- name = backend.name
- backends = getattr(module, 'BACKENDS', {})
- if name in backends and backends[name].enabled():
- BACKENDSCACHE[name] = backends[name]
- return BACKENDSCACHE
-
-
-def get_backend(name, *args, **kwargs):
- """Returns a backend by name. Backends are stored in the BACKENDSCACHE
- cache dict. If not found, each of the modules referenced in
- AUTHENTICATION_BACKENDS is imported and checked for a BACKENDS
- definition. If the named backend is found in the module's BACKENDS
- definition, it's then stored in the cache for future access.
- """
- try:
- # Cached backend which has previously been discovered.
- return BACKENDSCACHE[name](*args, **kwargs)
- except KeyError:
- # Force a reload of BACKENDS to ensure a missing
- # backend hasn't been missed.
- get_backends(force_load=True)
- try:
- return BACKENDSCACHE[name](*args, **kwargs)
- except KeyError:
- return None
+ return load_backends(getattr(settings, 'AUTHENTICATION_BACKENDS', []),
+ force_load)
-BACKENDS = {
- 'openid': OpenIdAuth
-}
+# placate pyflakes
+OpenIDBackend
+get_backend
View
95 social_auth/backends/amazon.py
@@ -1,94 +1 @@
-import base64
-from urllib2 import Request, HTTPError
-from urllib import urlencode
-
-try:
- import json as simplejson
-except ImportError:
- try:
- import simplejson
- except ImportError:
- from django.utils import simplejson
-
-from social_auth.backends import BaseOAuth2, OAuthBackend
-from social_auth.utils import dsa_urlopen
-from social_auth.exceptions import AuthTokenError
-
-
-class AmazonBackend(OAuthBackend):
- """Amazon OAuth2 authentication backend"""
- name = 'amazon'
- # Default extra data to store
- EXTRA_DATA = [
- ('user_id', 'user_id'),
- ('postal_code', 'postal_code')
- ]
- ID_KEY = 'user_id'
-
- def get_user_details(self, response):
- """Return user details from amazon account"""
- name = response.get('name') or ''
- first_name = ''
- last_name = ''
- if name and ' ' in name:
- first_name, last_name = response.get('name').split(' ', 1)
- else:
- first_name = name
- return {'username': name,
- 'email': response.get('email'),
- 'fullname': name,
- 'first_name': first_name,
- 'last_name': last_name}
-
-
-class AmazonAuth(BaseOAuth2):
- """Amazon OAuth2 support"""
- REDIRECT_STATE = False
- AUTH_BACKEND = AmazonBackend
- AUTHORIZATION_URL = 'http://www.amazon.com/ap/oa'
- ACCESS_TOKEN_URL = 'https://api.amazon.com/auth/o2/token'
- SETTINGS_KEY_NAME = 'AMAZON_APP_ID'
- SETTINGS_SECRET_NAME = 'AMAZON_API_SECRET'
- SCOPE_VAR_NAME = 'AMAZON_EXTENDED_PERMISSIONS'
- DEFAULT_SCOPE = ['profile']
-
- @classmethod
- def refresh_token(cls, token, redirect_uri):
- data = cls.refresh_token_params(token)
- data['redirect_uri'] = redirect_uri
- request = Request(cls.ACCESS_TOKEN_URL,
- data=urlencode(data),
- headers=cls.auth_headers())
- return cls.process_refresh_token_response(dsa_urlopen(request).read())
-
- def user_data(self, access_token, *args, **kwargs):
- """Grab user profile information from amazon."""
- url = 'https://www.amazon.com/ap/user/profile?access_token=%s' % \
- access_token
- try:
- response = simplejson.load(dsa_urlopen(Request(url)))
- except ValueError:
- return None
- except HTTPError:
- raise AuthTokenError(self)
- else:
- if 'Profile' in response:
- response = {
- 'user_id': response['Profile']['CustomerId'],
- 'name': response['Profile']['Name'],
- 'email': response['Profile']['PrimaryEmail']
- }
- return response
-
- @classmethod
- def auth_headers(cls):
- return {
- 'Authorization': 'Basic %s' % base64.urlsafe_b64encode(
- '%s:%s' % cls.get_key_and_secret()
- )
- }
-
-
-BACKENDS = {
- 'amazon': AmazonAuth
-}
+from social.backends.amazon import AmazonOAuth2 as AmazonBackend
View
29 social_auth/backends/aol.py
@@ -1,28 +1 @@
-"""
-AOL OpenID support
-
-No extra configurations are needed to make this work.
-"""
-from social_auth.backends import OpenIdAuth, OpenIDBackend
-
-
-AOL_OPENID_URL = 'http://openid.aol.com'
-
-# Backends
-class AolBackend(OpenIDBackend):
- """Aol OpenID authentication backend"""
- name = 'aol'
-
-# Auth classes
-class AolAuth(OpenIdAuth):
- """Aol OpenID authentication"""
- AUTH_BACKEND = AolBackend
-
- def openid_url(self):
- """Return AOL OpenID service url"""
- return AOL_OPENID_URL
-
-# Backend definition
-BACKENDS = {
- 'aol': AolAuth,
-}
+from social.backends.aol import AOLOpenId as AolBackend
View
93 social_auth/backends/browserid.py
@@ -1,92 +1 @@
-"""
-BrowserID support
-"""
-from urllib import urlencode
-
-try:
- import json as simplejson
-except ImportError:
- try:
- import simplejson
- except ImportError:
- from django.utils import simplejson
-
-from django.contrib.auth import authenticate
-
-from social_auth.backends import SocialAuthBackend, BaseAuth
-from social_auth.utils import log, dsa_urlopen
-from social_auth.exceptions import AuthFailed, AuthMissingParameter
-
-
-# BrowserID verification server
-BROWSER_ID_SERVER = 'https://verifier.login.persona.org/verify'
-
-
-class BrowserIDBackend(SocialAuthBackend):
- """BrowserID authentication backend"""
- name = 'browserid'
-
- def get_user_id(self, details, response):
- """Use BrowserID email as ID"""
- return details['email']
-
- def get_user_details(self, response):
- """Return user details, BrowserID only provides Email."""
- # {'status': 'okay',
- # 'audience': 'localhost:8000',
- # 'expires': 1328983575529,
- # 'email': 'name@server.com',
- # 'issuer': 'login.persona.org'}
- email = response['email']
- return {'username': email.split('@', 1)[0],
- 'email': email,
- 'fullname': '',
- 'first_name': '',
- 'last_name': ''}
-
- def extra_data(self, user, uid, response, details):
- """Return users extra data"""
- return {
- 'audience': response['audience'],
- 'issuer': response['issuer']
- }
-
-
-# Auth classes
-class BrowserIDAuth(BaseAuth):
- """BrowserID authentication"""
- AUTH_BACKEND = BrowserIDBackend
-
- def auth_complete(self, *args, **kwargs):
- """Completes loging process, must return user instance"""
- if not 'assertion' in self.data:
- raise AuthMissingParameter(self, 'assertion')
-
- data = urlencode({
- 'assertion': self.data['assertion'],
- 'audience': self.request.get_host()
- })
-
- try:
- response = simplejson.load(dsa_urlopen(BROWSER_ID_SERVER,
- data=data))
- except ValueError:
- log('error', 'Could not load user data from BrowserID.',
- exc_info=True)
- else:
- if response.get('status') == 'failure':
- log('debug', 'Authentication failed.')
- raise AuthFailed(self)
-
- kwargs.update({
- 'auth': self,
- 'response': response,
- self.AUTH_BACKEND.name: True
- })
- return authenticate(*args, **kwargs)
-
-
-# Backend definition
-BACKENDS = {
- 'browserid': BrowserIDAuth
-}
+from social.backends.persona import PersonaAuth as BrowserIDBackend
View
77 social_auth/backends/contrib/angel.py
@@ -1,76 +1 @@
-"""
-settings.py should include the following:
-
- ANGEL_CLIENT_ID = '...'
- ANGEL_CLIENT_SECRET = '...'
-
-Optional scope to include 'email' and/or 'messages' separated by space:
-
- ANGEL_AUTH_EXTRA_ARGUMENTS = {'scope': 'email messages'}
-
-More information on scope can be found at https://angel.co/api/oauth/faq
-"""
-from urllib import urlencode
-
-try:
- import json as simplejson
-except ImportError:
- try:
- import simplejson
- except ImportError:
- from django.utils import simplejson
-
-from social_auth.backends import BaseOAuth2, OAuthBackend
-from social_auth.utils import dsa_urlopen
-
-
-ANGEL_SERVER = 'angel.co'
-ANGEL_AUTHORIZATION_URL = 'https://angel.co/api/oauth/authorize/'
-ANGEL_ACCESS_TOKEN_URL = 'https://angel.co/api/oauth/token/'
-ANGEL_CHECK_AUTH = 'https://api.angel.co/1/me/'
-
-
-class AngelBackend(OAuthBackend):
- name = 'angel'
-
- def get_user_id(self, details, response):
- return response['id']
-
- def get_user_details(self, response):
- """Return user details from Angel account"""
- username = response['angellist_url'].split('/')[-1]
- first_name = response['name'].split(' ')[0]
- last_name = response['name'].split(' ')[-1]
- email = response['email']
- return {
- 'username': username,
- 'first_name': first_name,
- 'last_name': last_name,
- 'email': email,
- }
-
-
-class AngelAuth(BaseOAuth2):
- """Angel OAuth mechanism"""
- AUTHORIZATION_URL = ANGEL_AUTHORIZATION_URL
- ACCESS_TOKEN_URL = ANGEL_ACCESS_TOKEN_URL
- AUTH_BACKEND = AngelBackend
- SETTINGS_KEY_NAME = 'ANGEL_CLIENT_ID'
- SETTINGS_SECRET_NAME = 'ANGEL_CLIENT_SECRET'
- REDIRECT_STATE = False
- STATE_PARAMETER = False
-
- def user_data(self, access_token, *args, **kwargs):
- """Loads user data from service"""
- params = {'access_token': access_token}
- url = ANGEL_CHECK_AUTH + '?' + urlencode(params)
- try:
- return simplejson.load(dsa_urlopen(url))
- except ValueError:
- return None
-
-
-# Backend definition
-BACKENDS = {
- 'angel': AngelAuth,
-}
+from social.backends.angel import AngelOAuth2 as AngelBackend
View
68 social_auth/backends/contrib/appsfuel.py
@@ -1,66 +1,2 @@
-"""
-This module is originally written: django-social-auth-appsfuel==1.0.0
-You could refer to https://github.com/AppsFuel/django-social-auth-appsfuel for issues
-
-settings.py should include the following:
-
- APPSFUEL_CLIENT_ID = '...'
- APPSFUEL_CLIENT_SECRET = '...'
-
-"""
-import json
-from urllib import urlencode
-from social_auth.backends import BaseOAuth2, OAuthBackend
-from social_auth.utils import dsa_urlopen
-
-
-class AppsfuelBackend(OAuthBackend):
- name = 'appsfuel'
-
- def get_user_id(self, details, response):
- return response['user_id']
-
- def get_user_details(self, response):
- """Return user details from Appsfuel account"""
- fullname = response.get('display_name', '')
- email = response.get('email', '')
- username = email.split('@')[0] if email else ''
- return {
- 'username': username,
- 'first_name': fullname,
- 'email': email
- }