[Python-modules-commits] [python-social-auth] 230/322: Improve http error handling on auth_complete/do_auth. Fixes #304

Wolfgang Borgert debacle at moszumanska.debian.org
Sat Dec 24 15:13:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to tag v0.2.10
in repository python-social-auth.

commit 7dd4273f9fcc6d12516c699f6eb8dfda8242ac8e
Author: Matías Aguirre <matiasaguirre at gmail.com>
Date:   Sat Apr 4 03:47:42 2015 -0300

    Improve http error handling on auth_complete/do_auth. Fixes #304
---
 social/backends/beats.py    | 25 ++++++++-----------------
 social/backends/facebook.py |  3 ++-
 social/backends/google.py   | 24 +++++++++---------------
 social/backends/jawbone.py  | 23 ++++++++---------------
 social/backends/lastfm.py   |  2 ++
 social/backends/oauth.py    | 35 ++++++++++++-----------------------
 social/backends/persona.py  |  2 ++
 social/backends/pocket.py   |  2 ++
 social/backends/shopify.py  |  9 ++-------
 social/backends/yahoo.py    | 26 +++++++++-----------------
 social/exceptions.py        |  6 ++++++
 social/utils.py             | 20 +++++++++++++++++++-
 12 files changed, 81 insertions(+), 96 deletions(-)

diff --git a/social/backends/beats.py b/social/backends/beats.py
index d5801eb..d1d8772 100644
--- a/social/backends/beats.py
+++ b/social/backends/beats.py
@@ -4,9 +4,7 @@ Beats backend, docs at:
 """
 import base64
 
-from requests import HTTPError
-
-from social.exceptions import AuthCanceled, AuthUnknownError
+from social.utils import handle_http_errors
 from social.backends.oauth import BaseOAuth2
 
 
@@ -30,23 +28,16 @@ class BeatsOAuth2(BaseOAuth2):
             ))
         }
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         self.process_error(self.data)
-        try:
-            response = self.request_access_token(
-                self.ACCESS_TOKEN_URL,
-                data=self.auth_complete_params(self.validate_state()),
-                headers=self.auth_headers(),
-                method=self.ACCESS_TOKEN_METHOD
-            )
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
-        except KeyError:
-            raise AuthUnknownError(self)
+        response = self.request_access_token(
+            self.ACCESS_TOKEN_URL,
+            data=self.auth_complete_params(self.validate_state()),
+            headers=self.auth_headers(),
+            method=self.ACCESS_TOKEN_METHOD
+        )
         self.process_error(response)
         # mashery wraps in jsonrpc
         if response.get('jsonrpc', None):
diff --git a/social/backends/facebook.py b/social/backends/facebook.py
index 17b5238..3de7573 100644
--- a/social/backends/facebook.py
+++ b/social/backends/facebook.py
@@ -8,7 +8,7 @@ import json
 import base64
 import hashlib
 
-from social.utils import parse_qs, constant_time_compare
+from social.utils import parse_qs, constant_time_compare, handle_http_errors
 from social.backends.oauth import BaseOAuth2
 from social.exceptions import AuthException, AuthCanceled, AuthUnknownError, \
                               AuthMissingParameter
@@ -62,6 +62,7 @@ class FacebookOAuth2(BaseOAuth2):
             raise AuthCanceled(self, data.get('error_message') or
                                      data.get('error_code'))
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         self.process_error(self.data)
diff --git a/social/backends/google.py b/social/backends/google.py
index 2536152..a58549a 100644
--- a/social/backends/google.py
+++ b/social/backends/google.py
@@ -2,11 +2,10 @@
 Google OpenId, OAuth2, OAuth1, Google+ Sign-in backends, docs at:
     http://psa.matiasaguirre.net/docs/backends/google.html
 """
-from requests import HTTPError
-
+from social.utils import handle_http_errors
 from social.backends.open_id import OpenIdAuth, OpenIdConnectAuth
 from social.backends.oauth import BaseOAuth2, BaseOAuth1
-from social.exceptions import AuthMissingParameter, AuthCanceled
+from social.exceptions import AuthMissingParameter
 
 
 class BaseGoogleAuth(object):
@@ -135,6 +134,7 @@ class GooglePlusAuth(BaseGoogleOAuth2API, BaseOAuth2):
             params['redirect_uri'] = 'postmessage'
         return params
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         if 'access_token' in self.data and 'code' not in self.data:
             raise AuthMissingParameter(self, 'access_token or code')
@@ -147,18 +147,12 @@ class GooglePlusAuth(BaseGoogleOAuth2API, BaseOAuth2):
                 params={'access_token': token}
             ))
 
-        try:
-            response = self.request_access_token(
-                self.ACCESS_TOKEN_URL,
-                data=self.auth_complete_params(),
-                headers=self.auth_headers(),
-                method=self.ACCESS_TOKEN_METHOD
-            )
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
+        response = self.request_access_token(
+            self.ACCESS_TOKEN_URL,
+            data=self.auth_complete_params(),
+            headers=self.auth_headers(),
+            method=self.ACCESS_TOKEN_METHOD
+        )
         self.process_error(response)
         return self.do_auth(response['access_token'], response=response,
                             *args, **kwargs)
diff --git a/social/backends/jawbone.py b/social/backends/jawbone.py
index cf67359..52c84ce 100644
--- a/social/backends/jawbone.py
+++ b/social/backends/jawbone.py
@@ -2,7 +2,7 @@
 Jawbone OAuth2 backend, docs at:
     http://psa.matiasaguirre.net/docs/backends/jawbone.html
 """
-from requests import HTTPError
+from social.utils import handle_http_errors
 from social.backends.oauth import BaseOAuth2
 from social.exceptions import AuthCanceled, AuthUnknownError
 
@@ -62,23 +62,16 @@ class JawboneOAuth2(BaseOAuth2):
             'client_secret': client_secret,
         }
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         self.process_error(self.data)
-        try:
-            response = self.request_access_token(
-                self.ACCESS_TOKEN_URL,
-                params=self.auth_complete_params(self.validate_state()),
-                headers=self.auth_headers(),
-                method=self.ACCESS_TOKEN_METHOD
-            )
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
-        except KeyError:
-            raise AuthUnknownError(self)
+        response = self.request_access_token(
+            self.ACCESS_TOKEN_URL,
+            params=self.auth_complete_params(self.validate_state()),
+            headers=self.auth_headers(),
+            method=self.ACCESS_TOKEN_METHOD
+        )
         self.process_error(response)
         return self.do_auth(response['access_token'], response=response,
                             *args, **kwargs)
diff --git a/social/backends/lastfm.py b/social/backends/lastfm.py
index c9ea837..0f1acf9 100644
--- a/social/backends/lastfm.py
+++ b/social/backends/lastfm.py
@@ -1,5 +1,6 @@
 import hashlib
 
+from social.utils import handle_http_errors
 from social.backends.base import BaseAuth
 
 
@@ -21,6 +22,7 @@ class LastFmAuth(BaseAuth):
     def auth_url(self):
         return self.AUTH_URL.format(api_key=self.setting('KEY'))
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes login process, must return user instance"""
         key, secret = self.get_key_and_secret()
diff --git a/social/backends/oauth.py b/social/backends/oauth.py
index 717092d..0fa17cc 100644
--- a/social/backends/oauth.py
+++ b/social/backends/oauth.py
@@ -1,11 +1,10 @@
 import six
 
-from requests import HTTPError
 from requests_oauthlib import OAuth1
 from oauthlib.oauth1 import SIGNATURE_TYPE_AUTH_HEADER
 
 from social.p3 import urlencode, unquote
-from social.utils import url_add_parameters, parse_qs
+from social.utils import url_add_parameters, parse_qs, handle_http_errors
 from social.exceptions import AuthFailed, AuthCanceled, AuthUnknownError, \
                               AuthMissingParameter, AuthStateMissing, \
                               AuthStateForbidden, AuthTokenError
@@ -170,21 +169,17 @@ class BaseOAuth1(OAuthAuth):
                 raise AuthCanceled(self, 'User refused the access')
             raise AuthUnknownError(self, 'Error was ' + data['oauth_problem'])
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Return user, might be logged in"""
         # Multiple unauthorized tokens are supported (see #521)
         self.process_error(self.data)
         self.validate_state()
         token = self.get_unauthorized_token()
-        try:
-            access_token = self.access_token(token)
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
+        access_token = self.access_token(token)
         return self.do_auth(access_token, *args, **kwargs)
 
+    @handle_http_errors
     def do_auth(self, access_token, *args, **kwargs):
         """Finish the auth process once the access_token was retrieved"""
         if not isinstance(access_token, dict):
@@ -356,28 +351,22 @@ class BaseOAuth2(OAuthAuth):
         elif 'denied' in data:
             raise AuthCanceled(self, data['denied'])
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         state = self.validate_state()
         self.process_error(self.data)
-        try:
-            response = self.request_access_token(
-                self.access_token_url(),
-                data=self.auth_complete_params(state),
-                headers=self.auth_headers(),
-                method=self.ACCESS_TOKEN_METHOD
-            )
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
-        except KeyError:
-            raise AuthUnknownError(self)
+        response = self.request_access_token(
+            self.access_token_url(),
+            data=self.auth_complete_params(state),
+            headers=self.auth_headers(),
+            method=self.ACCESS_TOKEN_METHOD
+        )
         self.process_error(response)
         return self.do_auth(response['access_token'], response=response,
                             *args, **kwargs)
 
+    @handle_http_errors
     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)
diff --git a/social/backends/persona.py b/social/backends/persona.py
index 060715c..054ea2f 100644
--- a/social/backends/persona.py
+++ b/social/backends/persona.py
@@ -2,6 +2,7 @@
 Mozilla Persona authentication backend, docs at:
     http://psa.matiasaguirre.net/docs/backends/persona.html
 """
+from social.utils import handle_http_errors
 from social.backends.base import BaseAuth
 from social.exceptions import AuthFailed, AuthMissingParameter
 
@@ -33,6 +34,7 @@ class PersonaAuth(BaseAuth):
         return {'audience': response['audience'],
                 'issuer': response['issuer']}
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         if 'assertion' not in self.data:
diff --git a/social/backends/pocket.py b/social/backends/pocket.py
index 90bc5a9..0852d31 100644
--- a/social/backends/pocket.py
+++ b/social/backends/pocket.py
@@ -3,6 +3,7 @@ Pocket OAuth2 backend, docs at:
     http://psa.matiasaguirre.net/docs/backends/pocket.html
 """
 from social.backends.base import BaseAuth
+from social.utils import handle_http_errors
 
 
 class PocketAuth(BaseAuth):
@@ -33,6 +34,7 @@ class PocketAuth(BaseAuth):
         bits = (self.AUTHORIZATION_URL, token, self.redirect_uri)
         return '%s?request_token=%s&redirect_uri=%s' % bits
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         data = {
             'consumer_key': self.setting('POCKET_CONSUMER_KEY'),
diff --git a/social/backends/shopify.py b/social/backends/shopify.py
index 4078567..214fd18 100644
--- a/social/backends/shopify.py
+++ b/social/backends/shopify.py
@@ -5,8 +5,7 @@ Shopify OAuth2 backend, docs at:
 import imp
 import six
 
-from requests import HTTPError
-
+from social.utils import handle_http_errors
 from social.backends.oauth import BaseOAuth2
 from social.exceptions import AuthFailed, AuthCanceled
 
@@ -61,6 +60,7 @@ class ShopifyOAuth2(BaseOAuth2):
             redirect_uri=redirect_uri
         )
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes login process, must return user instance"""
         self.process_error(self.data)
@@ -73,11 +73,6 @@ class ShopifyOAuth2(BaseOAuth2):
             access_token = shopify_session.token
         except self.shopifyAPI.ValidationException:
             raise AuthCanceled(self)
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
         else:
             if not access_token:
                 raise AuthFailed(self, 'Authentication Failed')
diff --git a/social/backends/yahoo.py b/social/backends/yahoo.py
index 7ab046d..15fc9d1 100644
--- a/social/backends/yahoo.py
+++ b/social/backends/yahoo.py
@@ -2,12 +2,11 @@
 Yahoo OpenId, OAuth1 and OAuth2 backends, docs at:
     http://psa.matiasaguirre.net/docs/backends/yahoo.html
 """
-from requests import HTTPError
 from requests.auth import HTTPBasicAuth
 
+from social.utils import handle_http_errors
 from social.backends.open_id import OpenIdAuth
 from social.backends.oauth import BaseOAuth2, BaseOAuth1
-from social.exceptions import AuthCanceled, AuthUnknownError
 
 
 class YahooOpenId(OpenIdAuth):
@@ -113,24 +112,17 @@ class YahooOAuth2(BaseOAuth2):
             'Authorization': 'Bearer {0}'.format(access_token)
         }, method='GET')['profile']
 
+    @handle_http_errors
     def auth_complete(self, *args, **kwargs):
         """Completes loging process, must return user instance"""
         self.process_error(self.data)
-        try:
-            response = self.request_access_token(
-                self.ACCESS_TOKEN_URL,
-                auth=HTTPBasicAuth(*self.get_key_and_secret()),
-                data=self.auth_complete_params(self.validate_state()),
-                headers=self.auth_headers(),
-                method=self.ACCESS_TOKEN_METHOD
-            )
-        except HTTPError as err:
-            if err.response.status_code == 400:
-                raise AuthCanceled(self)
-            else:
-                raise
-        except KeyError:
-            raise AuthUnknownError(self)
+        response = self.request_access_token(
+            self.ACCESS_TOKEN_URL,
+            auth=HTTPBasicAuth(*self.get_key_and_secret()),
+            data=self.auth_complete_params(self.validate_state()),
+            headers=self.auth_headers(),
+            method=self.ACCESS_TOKEN_METHOD
+        )
         self.process_error(response)
         return self.do_auth(response['access_token'], response=response,
                             *args, **kwargs)
diff --git a/social/exceptions.py b/social/exceptions.py
index b4b8b2f..88e1155 100644
--- a/social/exceptions.py
+++ b/social/exceptions.py
@@ -98,6 +98,12 @@ class AuthForbidden(AuthException):
         return 'Your credentials aren\'t allowed'
 
 
+class AuthUnreachableProvider(AuthException):
+    """Cannot reach the provider"""
+    def __str__(self):
+        return 'The authentication provider could not be reached'
+
+
 class InvalidEmail(AuthException):
     def __str__(self):
         return 'Email couldn\'t be validated'
diff --git a/social/utils.py b/social/utils.py
index 0ceb54f..266dc71 100644
--- a/social/utils.py
+++ b/social/utils.py
@@ -2,10 +2,13 @@ import re
 import sys
 import unicodedata
 import collections
-import six
+import functools
 
+import six
+import requests
 import social
 
+from social.exceptions import AuthCanceled, AuthUnreachableProvider
 from social.p3 import urlparse, urlunparse, urlencode, \
                       parse_qs as battery_parse_qs
 
@@ -187,3 +190,18 @@ def setting_url(backend, *names):
             value = backend.setting(name)
             if is_url(value):
                 return value
+
+
+def handle_http_errors(func):
+    @functools.wraps(func)
+    def wrapper(*args, **kwargs):
+        try:
+            return func(*args, **kwargs)
+        except requests.HTTPError as err:
+            if err.response.status_code == 400:
+                raise AuthCanceled(args[0])
+            elif err.response.status_code == 503:
+                raise AuthUnreachableProvider(args[0])
+            else:
+                raise
+    return wrapper

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-social-auth.git



More information about the Python-modules-commits mailing list