Skip to content

Commit

Permalink
Use connection pooling with requests for Google and Facebook OAuth2
Browse files Browse the repository at this point in the history
  • Loading branch information
talos committed Oct 1, 2012
1 parent 2f6cbce commit fe0ea3d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 48 deletions.
89 changes: 50 additions & 39 deletions social_auth/backends/__init__.py
Expand Up @@ -9,7 +9,8 @@
(which is used for URLs matching) and Auth class, otherwise it won't be
enabled.
"""
from urllib2 import Request, urlopen, HTTPError
from urllib2 import urlopen, HTTPError
import requests
from urllib import urlencode

from openid.consumer.consumer import Consumer, SUCCESS, CANCEL, FAILURE
Expand All @@ -36,7 +37,6 @@
AuthStateForbidden
from social_auth.backends.utils import build_consumer_oauth_request


# OpenID configuration
OLD_AX_ATTRS = [
('http://schema.openid.net/contact/email', 'old_email'),
Expand Down Expand Up @@ -87,37 +87,44 @@ def authenticate(self, *args, **kwargs):
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
try:
# 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
except Exception as e:
import traceback
log('warn', 'Uncaught exception in authenticate: %s' % e)
log('warn', 'Traceback: %s' % traceback.format_exc())
raise

def pipeline(self, pipeline, *args, **kwargs):
"""Pipeline"""
Expand Down Expand Up @@ -721,16 +728,19 @@ def auth_complete(self, *args, **kwargs):
}
headers = {'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'}
request = Request(self.ACCESS_TOKEN_URL, data=urlencode(params),
headers=headers)
#request = Request(self.ACCESS_TOKEN_URL, data=urlencode(params),
# headers=headers)

try:
response = simplejson.loads(urlopen(request).read())
except HTTPError, e:
if e.code == 400:
raise AuthCanceled(self)
#response = simplejson.loads(urlopen(request).read())
http_response = requests.post(self.ACCESS_TOKEN_URL,
data=params,
headers=headers)

if http_response.status_code == 200:
response = simplejson.loads(http_response.text)
else:
raise
raise AuthCanceled(self)
except (ValueError, KeyError):
raise AuthUnknownError(self)

Expand All @@ -739,6 +749,7 @@ def auth_complete(self, *args, **kwargs):
raise AuthFailed(self, error)
else:
data = self.user_data(response['access_token'], response)

response.update(data or {})
kwargs.update({
'auth': self,
Expand Down
20 changes: 15 additions & 5 deletions social_auth/backends/facebook.py
Expand Up @@ -13,7 +13,8 @@
"""
import cgi
from urllib import urlencode
from urllib2 import urlopen, HTTPError
#from urllib2 import urlopen, HTTPError
import requests
import base64
import hmac
import hashlib
Expand Down Expand Up @@ -71,12 +72,16 @@ def user_data(self, access_token, *args, **kwargs):
url = FACEBOOK_ME + urlencode(params)

try:
data = simplejson.load(urlopen(url))
response = requests.get(url)
if response.status_code == 200:
data = simplejson.loads(response.text)
else:
raise AuthTokenError()
except ValueError:
extra = {'access_token': sanitize_log_data(access_token)}
log('error', 'Could not load user data from Facebook.',
exc_info=True, extra=extra)
except HTTPError:
except requests.RequestException:
extra = {'access_token': sanitize_log_data(access_token)}
log('error', 'Error validating access token.',
exc_info=True, extra=extra)
Expand All @@ -101,8 +106,13 @@ def auth_complete(self, *args, **kwargs):
'code': self.data['code']
})
try:
response = cgi.parse_qs(urlopen(url).read())
except HTTPError:
http_response = requests.get(url)
if http_response.status_code == 200:
response = cgi.parse_qs(http_response.text)
else:
raise AuthFailed(self, 'There was an error authenticating ' \
'the app')
except requests.RequestException:
raise AuthFailed(self, 'There was an error authenticating ' \
'the app')

Expand Down
13 changes: 9 additions & 4 deletions social_auth/backends/google.py
Expand Up @@ -13,7 +13,7 @@
OpenID also works straightforward, it doesn't need further configurations.
"""
from urllib import urlencode
#from urllib import urlencode
from urllib2 import Request, urlopen

from oauth2 import Request as OAuthRequest
Expand All @@ -25,6 +25,8 @@
OAuthBackend, OpenIDBackend, USERNAME
from social_auth.backends.exceptions import AuthFailed

import requests


# Google OAuth base configuration
GOOGLE_OAUTH_SERVER = 'www.google.com'
Expand Down Expand Up @@ -225,10 +227,13 @@ def googleapis_profile(url, access_token):
https://developers.google.com/accounts/docs/OAuth2Login
"""
data = {'access_token': access_token, 'alt': 'json'}
request = Request(url + '?' + urlencode(data))
try:
return simplejson.loads(urlopen(request).read())
except (ValueError, KeyError, IOError):
response = requests.get(url, params=data)
if response.status_code == 200:
return simplejson.loads(response.text)
else:
return None
except (ValueError, KeyError, requests.RequestException):
return None


Expand Down

0 comments on commit fe0ea3d

Please sign in to comment.