]> git.parisson.com Git - django-social-auth.git/commitdiff
Deprecate /associate/ URLs in favor of /login/ and /complete/ with user.is_authentica...
authorMatías Aguirre <matiasaguirre@gmail.com>
Wed, 18 Apr 2012 16:29:12 +0000 (13:29 -0300)
committerMatías Aguirre <matiasaguirre@gmail.com>
Wed, 18 Apr 2012 16:29:12 +0000 (13:29 -0300)
README.rst
doc/deprecated.rst
example/templates/done.html
social_auth/decorators.py [new file with mode: 0644]
social_auth/urls.py
social_auth/views.py

index 5fe7f111f6019a704311db72a1176b69d2b895a9..e515169d645d441e18ec59ed15a522618ba46225 100644 (file)
@@ -494,6 +494,7 @@ The following settings are deprecated in favor of pipeline functions.
     SOCIAL_AUTH_DEFAULT_USERNAME
     SOCIAL_AUTH_UUID_LENGTH
     SOCIAL_AUTH_USERNAME_FIXER
+    SOCIAL_AUTH_ASSOCIATE_URL_NAME
 
 - User creation setting should be avoided and remove the entry ``create_user``
   from pipeline instead::
@@ -515,6 +516,18 @@ The following settings are deprecated in favor of pipeline functions.
 
     SOCIAL_AUTH_ASSOCIATE_BY_MAIL
 
+- Associate URLs are deprecated since the login ones can handle the case, this
+  avoids issues where providers check the redirect URI and redirects to the
+  configured value in the application. So, from now on a single entry point is
+  recommended being::
+
+        /<social auth path>/login/<backend>/
+
+  And to complete the process::
+
+        /<social auth path>/complete/<backend>/
+
+
 Usage example
 -------------
 
index 60d3ff60c4480fcbceb9999dd345d87ca064f532..9efafca76cfba366a929c8033a08c5bb3861f9a0 100644 (file)
@@ -10,6 +10,7 @@ The following settings are deprecated in favor of pipeline functions.
     SOCIAL_AUTH_DEFAULT_USERNAME
     SOCIAL_AUTH_UUID_LENGTH
     SOCIAL_AUTH_USERNAME_FIXER
+    SOCIAL_AUTH_ASSOCIATE_URL_NAME
 
 - User creation setting should be avoided and remove the entry ``create_user``
   from pipeline instead::
@@ -30,3 +31,14 @@ The following settings are deprecated in favor of pipeline functions.
   ``associate_by_email`` pipeline entry instead of using this setting::
 
     SOCIAL_AUTH_ASSOCIATE_BY_MAIL
+
+- Associate URLs are deprecated since the login ones can handle the case, this
+  avoids issues where providers check the redirect URI and redirects to the
+  configured value in the application. So, from now on a single entry point is
+  recommended being::
+
+        /<social auth path>/login/<backend>/
+
+  And to complete the process::
+
+        /<social auth path>/complete/<backend>/
index 2ef4e0dc13011d59a73404c0c76df53a4d01fe91..c21d950f619c3a4a2a7d41c6e880790bb0ea753d 100644 (file)
   <h3>Associate new <a href="http://oauth.net/" title="OAuth">OAuth</a> credentials:</h3>
   <ul>
   {% for name in social_auth.backends.oauth %}
-    <li><a rel="nofollow" href="{% url socialauth_associate_begin name %}">{{ name|title }}</a></li>
+    <li><a rel="nofollow" href="{% url socialauth_begin name %}">{{ name|title }}</a></li>
   {% endfor %}
   </ul>
 
   <h3>Associate new <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-10" title="OAuth2">OAuth2</a> credentials:</h3>
   <ul>
   {% for name in social_auth.backends.oauth2 %}
-    <li><a rel="nofollow" href="{% url socialauth_associate_begin name %}">{{ name|title }}</a></li>
+    <li><a rel="nofollow" href="{% url socialauth_begin name %}">{{ name|title }}</a></li>
   {% endfor %}
   </ul>
 
   {% for name in social_auth.backends.openid %}
     <li>
     {% if name != "livejournal" and name != "openid" %}
-      <a rel="nofollow" href="{% url socialauth_associate_begin name %}">{{ name|title }}</a>
+      <a rel="nofollow" href="{% url socialauth_begin name %}">{{ name|title }}</a>
     {% else %}
       {% if name == "livejournal" %}
-      <form action="{% url socialauth_associate_begin "livejournal" %}" method="post">{% csrf_token %}
+      <form action="{% url socialauth_begin "livejournal" %}" method="post">{% csrf_token %}
         <div>
           <label for="openid_lj_user">LiveJournal user:</label>
           <input id="openid_lj_user" type="text" value="" name="openid_lj_user" />
@@ -65,7 +65,7 @@
       </form>
       {% else %}
         {% if name == "openid" %}
-        <form action="{% url socialauth_associate_begin "openid" %}" method="post">{% csrf_token %}
+        <form action="{% url socialauth_begin "openid" %}" method="post">{% csrf_token %}
           <div>
             <label for="openid_identifier">Other provider</label>
             <input id="openid_identifier" type="text" value="" name="openid_identifier" />
diff --git a/social_auth/decorators.py b/social_auth/decorators.py
new file mode 100644 (file)
index 0000000..cf10eb8
--- /dev/null
@@ -0,0 +1,58 @@
+from functools import wraps
+
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, HttpResponseServerError
+from django.utils.importlib import import_module
+
+from social_auth.backends import get_backend
+from social_auth.utils import setting, log, backend_setting
+
+
+LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL'))
+RAISE_EXCEPTIONS = setting('SOCIAL_AUTH_RAISE_EXCEPTIONS', setting('DEBUG'))
+PROCESS_EXCEPTIONS = setting('SOCIAL_AUTH_PROCESS_EXCEPTIONS',
+                             'social_auth.utils.log_exceptions_to_messages')
+
+
+def dsa_view(redirect_name=None):
+    """Decorate djangos-social-auth views. Will check and retrieve backend
+    or return HttpResponseServerError if backend is not found.
+
+        redirect_name parameter is used to build redirect URL used by backend.
+    """
+    def dec(func):
+        @wraps(func)
+        def wrapper(request, backend, *args, **kwargs):
+            if redirect_name:
+                redirect = reverse(redirect_name, args=(backend,))
+            else:
+                redirect = request.path
+            backend = get_backend(backend, request, redirect)
+
+            if not backend:
+                return HttpResponseServerError('Incorrect authentication ' + \
+                                               'service')
+
+            try:
+                return func(request, backend, *args, **kwargs)
+            except Exception, e:  # some error ocurred
+                if RAISE_EXCEPTIONS:
+                    raise
+                log('error', unicode(e), exc_info=True, extra={
+                    'request': request
+                })
+
+                mod, func_name = PROCESS_EXCEPTIONS.rsplit('.', 1)
+                try:
+                    process = getattr(import_module(mod), func_name,
+                                      lambda *args: None)
+                except ImportError:
+                    pass
+                else:
+                    process(request, backend, e)
+
+                url = backend_setting(backend, 'SOCIAL_AUTH_BACKEND_ERROR_URL',
+                                      LOGIN_ERROR_URL)
+                return HttpResponseRedirect(url)
+        return wrapper
+    return dec
index 3d41d3c5a36243a4b2b69644595c69446fff0de0..512aae5b5e9701764e701a7dd66bb65b0f59010a 100644 (file)
@@ -1,8 +1,7 @@
 """URLs module"""
 from django.conf.urls.defaults import patterns, url
 
-from social_auth.views import auth, complete, associate, associate_complete, \
-                              disconnect
+from social_auth.views import auth, complete, disconnect
 
 
 urlpatterns = patterns('',
@@ -12,10 +11,12 @@ urlpatterns = patterns('',
     url(r'^complete/(?P<backend>[^/]+)/$', complete,
         name='socialauth_complete'),
 
-    # association
-    url(r'^associate/(?P<backend>[^/]+)/$', associate,
+    # XXX: Deprecated, this URLs are deprecated, instead use the login and
+    #      complete ones directly, they will differentiate the user intention
+    #      by checking it's authenticated status association.
+    url(r'^associate/(?P<backend>[^/]+)/$', auth,
         name='socialauth_associate_begin'),
-    url(r'^associate/complete/(?P<backend>[^/]+)/$', associate_complete,
+    url(r'^associate/complete/(?P<backend>[^/]+)/$', complete,
         name='socialauth_associate_complete'),
 
     # disconnection
index 45808a8ef8caa5646f08dc00ca5b5c514bf04a8f..13bd3308004ad3dd894f997eeeb954ecba5e033e 100644 (file)
@@ -5,72 +5,20 @@ Notes:
       on third party providers that (if using POST) won't be sending csrf
       token back.
 """
-from functools import wraps
-
-from django.http import HttpResponseRedirect, HttpResponse, \
-                        HttpResponseServerError
-from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect, HttpResponse
 from django.contrib.auth import login, REDIRECT_FIELD_NAME
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
-from django.utils.importlib import import_module
 from django.views.decorators.csrf import csrf_exempt
 
-from social_auth.backends import get_backend
-from social_auth.utils import sanitize_redirect, setting, log, \
+from social_auth.utils import sanitize_redirect, setting, \
                               backend_setting, clean_partial_pipeline
+from social_auth.decorators import dsa_view
 
 
 DEFAULT_REDIRECT = setting('SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \
                    setting('LOGIN_REDIRECT_URL')
 LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL'))
-RAISE_EXCEPTIONS = setting('SOCIAL_AUTH_RAISE_EXCEPTIONS', setting('DEBUG'))
-PROCESS_EXCEPTIONS = setting('SOCIAL_AUTH_PROCESS_EXCEPTIONS',
-                             'social_auth.utils.log_exceptions_to_messages')
-
-
-def dsa_view(redirect_name=None):
-    """Decorate djangos-social-auth views. Will check and retrieve backend
-    or return HttpResponseServerError if backend is not found.
-
-        redirect_name parameter is used to build redirect URL used by backend.
-    """
-    def dec(func):
-        @wraps(func)
-        def wrapper(request, backend, *args, **kwargs):
-            if redirect_name:
-                redirect = reverse(redirect_name, args=(backend,))
-            else:
-                redirect = request.path
-            backend = get_backend(backend, request, redirect)
-
-            if not backend:
-                return HttpResponseServerError('Incorrect authentication ' + \
-                                               'service')
-
-            try:
-                return func(request, backend, *args, **kwargs)
-            except Exception, e:  # some error ocurred
-                if RAISE_EXCEPTIONS:
-                    raise
-                log('error', unicode(e), exc_info=True, extra={
-                    'request': request
-                })
-
-                mod, func_name = PROCESS_EXCEPTIONS.rsplit('.', 1)
-                try:
-                    process = getattr(import_module(mod), func_name,
-                                      lambda *args: None)
-                except ImportError:
-                    pass
-                else:
-                    process(request, backend, e)
-
-                url = backend_setting(backend, 'SOCIAL_AUTH_BACKEND_ERROR_URL',
-                                      LOGIN_ERROR_URL)
-                return HttpResponseRedirect(url)
-        return wrapper
-    return dec
 
 
 @dsa_view(setting('SOCIAL_AUTH_COMPLETE_URL_NAME', 'socialauth_complete'))
@@ -84,20 +32,13 @@ def auth(request, backend):
 def complete(request, backend, *args, **kwargs):
     """Authentication complete view, override this view if transaction
     management doesn't suit your needs."""
-    return complete_process(request, backend, *args, **kwargs)
-
-
-@login_required
-@dsa_view(setting('SOCIAL_AUTH_ASSOCIATE_URL_NAME',
-                  'socialauth_associate_complete'))
-def associate(request, backend):
-    """Authentication starting process"""
-    return auth_process(request, backend)
+    if request.user.is_authenticated():
+        return associate_complete(request, backend, *args, **kwargs)
+    else:
+        return complete_process(request, backend, *args, **kwargs)
 
 
-@csrf_exempt
 @login_required
-@dsa_view()
 def associate_complete(request, backend, *args, **kwargs):
     """Authentication complete process"""
     # pop redirect value before the session is trashed on login()