def get(self, provider=None): """ Handle login initiation via a known OAuth 2 provider. """ if settings.DEBUG and provider == "dummy": # Handle test dev login auth_id = 'dummy:test' UserPrefs.create_or_update( auth_id, { 'id': '1234', 'name': 'Test User', 'email': '*****@*****.**', 'avatar': 'http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s={0}&d=identicon' }, {}) # Update session self.session['auth_id'] = auth_id return self.redirect(self.session.pop('next', '/')) auth_url = AUTH_URLS[provider][0] key = getattr(settings, provider.upper() + '_OAUTH_KEY') scope = getattr(settings, provider.upper() + '_OAUTH_SCOPE') # Generate a random state parameter to prevent CSRF attacks # This is both stored in the session and sent to the authorizing # server, relayed back and then checked to make sure it matches # up. If not, then the request likely did not originate from # this site and it can be ignored. csrf_state = hashlib.md5(uuid.uuid4().hex).hexdigest() self.session['login_csrf'] = csrf_state params = { 'response_type': 'code', 'client_id': key, 'redirect_uri': self.callback_url(provider), 'state': csrf_state } if scope: params.update(scope=scope) target_url = auth_url.format(urlencode(params)) logging.info('Redirecting user to %s', target_url) self.redirect(target_url)
def get(self, provider=None): """ Handle login initiation via a known OAuth 2 provider. """ if settings.DEBUG and provider == "dummy": # Handle test dev login auth_id = 'dummy:test' UserPrefs.create_or_update(auth_id, { 'id': '1234', 'name': 'Test User', 'email': '*****@*****.**', 'avatar': 'http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s={0}&d=identicon' }, {}) # Update session self.session['auth_id'] = auth_id return self.redirect(self.session.pop('next', '/')) auth_url = AUTH_URLS[provider][0] key = getattr(settings, provider.upper() + '_OAUTH_KEY') scope = getattr(settings, provider.upper() + '_OAUTH_SCOPE') # Generate a random state parameter to prevent CSRF attacks # This is both stored in the session and sent to the authorizing # server, relayed back and then checked to make sure it matches # up. If not, then the request likely did not originate from # this site and it can be ignored. csrf_state = hashlib.md5(uuid.uuid4().hex).hexdigest() self.session['login_csrf'] = csrf_state params = { 'response_type': 'code', 'client_id': key, 'redirect_uri': self.callback_url(provider), 'state': csrf_state } if scope: params.update(scope=scope) target_url = auth_url.format(urlencode(params)) logging.info('Redirecting user to %s', target_url) self.redirect(target_url)
def get(self, provider): # Did we get an error? error = self.request.get('error') if error: raise AuthProviderResponseError(error, provider) # At this point the user is successfully logged in, but we need to # get an access token in order to call the API which gets user # information like id, name, avatar, email, etc. Then we need # to actually call that API, and use the response to create a # user object within our data store. # Get the access code so we can exchange it for a token code = self.request.get('code') # Get the CSRF state state = self.request.get('state') if self.session['login_csrf'] != state: logging.warning("Login aborted due to possible CSRF!") return self.abort() # Get the access token using the access code key = getattr(settings, provider.upper() + '_OAUTH_KEY') secret = getattr(settings, provider.upper() + '_OAUTH_SECRET') payload = { 'code': code, 'client_id': key, 'client_secret': secret, 'redirect_uri': self.callback_url(provider), 'grant_type': 'authorization_code' } resp = urlfetch.fetch( url=AUTH_URLS[provider][1], payload=urlencode(payload), method=urlfetch.POST, headers={'Content-Type': 'application/x-www-form-urlencoded'} ) if provider in ['google', 'windows_live']: auth_info = json.loads(resp.content) elif provider in ['facebook']: auth_info = dict(urlparse.parse_qsl(resp.content)) else: raise NotImplementedError('Not sure how to parse access token response for ' + provider) logging.info(str(auth_info)) # Use access token to make an API call to get user info user_info = getattr(self, '_' + provider + '_user_info')(auth_info) # Create or update a user object in the data store auth_id = provider + ":" + str(user_info['id']) UserPrefs.create_or_update(auth_id, user_info, auth_info) # Update session self.session['auth_id'] = auth_id self.redirect(self.session.pop('next', '/dashboard'))
def get(self, provider): # Did we get an error? error = self.request.get('error') if error: raise AuthProviderResponseError(error, provider) # At this point the user is successfully logged in, but we need to # get an access token in order to call the API which gets user # information like id, name, avatar, email, etc. Then we need # to actually call that API, and use the response to create a # user object within our data store. # Get the access code so we can exchange it for a token code = self.request.get('code') # Get the CSRF state state = self.request.get('state') if self.session['login_csrf'] != state: logging.warning("Login aborted due to possible CSRF!") return self.abort() # Get the access token using the access code key = getattr(settings, provider.upper() + '_OAUTH_KEY') secret = getattr(settings, provider.upper() + '_OAUTH_SECRET') payload = { 'code': code, 'client_id': key, 'client_secret': secret, 'redirect_uri': self.callback_url(provider), 'grant_type': 'authorization_code' } resp = urlfetch.fetch( url=AUTH_URLS[provider][1], payload=urlencode(payload), method=urlfetch.POST, headers={'Content-Type': 'application/x-www-form-urlencoded'}) if provider in ['google', 'windows_live']: auth_info = json.loads(resp.content) elif provider in ['facebook']: auth_info = dict(urlparse.parse_qsl(resp.content)) else: raise NotImplementedError( 'Not sure how to parse access token response for ' + provider) logging.info(str(auth_info)) # Use access token to make an API call to get user info user_info = getattr(self, '_' + provider + '_user_info')(auth_info) # Create or update a user object in the data store auth_id = provider + ":" + str(user_info['id']) UserPrefs.create_or_update(auth_id, user_info, auth_info) # Update session self.session['auth_id'] = auth_id self.redirect(self.session.pop('next', '/dashboard'))