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") RAISE_EXCEPTIONS = backend_setting(backend, "SOCIAL_AUTH_RAISE_EXCEPTIONS", setting("DEBUG")) 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}) url = None mod, func_name = PROCESS_EXCEPTIONS.rsplit(".", 1) try: process = getattr(import_module(mod), func_name, lambda *args: None) except ImportError: pass else: url = process(request, backend, e) if not url: url = backend_setting(backend, "SOCIAL_AUTH_BACKEND_ERROR_URL", LOGIN_ERROR_URL) return HttpResponseRedirect(url)
def associate_complete(request, backend, *args, **kwargs): """Authentication complete process""" # pop redirect value before the session is trashed on login() redirect_value = request.session.get(REDIRECT_FIELD_NAME, '') user = auth_complete(request, backend, request.user, *args, **kwargs) if not user: url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL) elif isinstance(user, HttpResponse): return user else: url = backend_setting(backend, 'SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL') or \ redirect_value or \ DEFAULT_REDIRECT return HttpResponseRedirect(url)
def disconnect(request, backend, association_id=None): """Disconnects given backend from current logged in user.""" backend.disconnect(request.user, association_id) url = request.REQUEST.get(REDIRECT_FIELD_NAME, '') or \ backend_setting(backend, 'SOCIAL_AUTH_DISCONNECT_REDIRECT_URL') or \ DEFAULT_REDIRECT return HttpResponseRedirect(url)
def user_data(self, access_token, *args, **kwargs): """Loads user data from service""" data = None params = backend_setting(self, self.EXTRA_PARAMS_VAR_NAME, {}) params['access_token'] = access_token url = FACEBOOK_ME + urlencode(params) try: data = simplejson.load(dsa_urlopen(url)) 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: extra = {'access_token': sanitize_log_data(access_token)} log('error', 'Error validating access token.', exc_info=True, extra=extra) raise AuthTokenError(self) else: log('debug', 'Found user data for token %s', sanitize_log_data(access_token), extra={'data': data}) return data
def get_auth_sig(self): secret_key = backend_setting(self.auth, 'ODNOKLASSNIKI_APP_SECRET') hash_source = '{0:d}{1:s}{2:s}'.format( self.cleaned_data['logged_user_id'], self.cleaned_data['session_key'], secret_key ) return md5(hash_source).hexdigest()
def auth_complete(self, request, user, *args, **kwargs): form = OdnoklassnikiIframeForm(auth=self, data=request.GET) if not form.is_valid(): raise AuthFailed('Cannot authorize: malformed parameters') else: response = form.get_response() extra_user_data = backend_setting( self, 'ODNOKLASSNIKI_APP_EXTRA_USER_DATA_LIST', ()) base_fields = ('uid', 'first_name', 'last_name', 'name') fields = base_fields + extra_user_data data = { 'method': 'users.getInfo', 'uids': '{0}'.format(response['logged_user_id']), 'fields': ','.join(fields), } client_key, client_secret, public_key = self.get_settings() details = odnoklassniki_api(data, response['api_server'], public_key, client_secret, 'iframe_nosession') if len(details) == 1 and 'uid' in details[0]: details = details[0] auth_data_fields = backend_setting( self, 'ODNOKLASSNIKI_APP_EXTRA_AUTH_DATA_LIST', ('api_server', 'apiconnection', 'session_key', 'session_secret_key', 'authorized') ) for field in auth_data_fields: details[field] = response[field] details['extra_data_list'] = fields + auth_data_fields kwargs.update({ 'auth': self, 'response': details, self.AUTH_BACKEND.name: True }) else: raise AuthFailed('Cannot get user details: API error') return authenticate(*args, **kwargs)
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') RAISE_EXCEPTIONS = backend_setting(backend, 'SOCIAL_AUTH_RAISE_EXCEPTIONS', setting('DEBUG')) 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 }) url = None mod, func_name = PROCESS_EXCEPTIONS.rsplit('.', 1) try: process = getattr(import_module(mod), func_name, lambda *args: None) except ImportError: pass else: url = process(request, backend, e) if not url: url = backend_setting(backend, 'SOCIAL_AUTH_BACKEND_ERROR_URL', LOGIN_ERROR_URL) return HttpResponseRedirect(url)
def user_data(self, access_token, *args, **kwargs): """Loads user data from service""" data = None params = backend_setting(self, self.EXTRA_PARAMS_VAR_NAME, {}) params["access_token"] = access_token url = FACEBOOK_ME + urlencode(params) try: data = simplejson.load(dsa_urlopen(url)) 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: extra = {"access_token": sanitize_log_data(access_token)} log("error", "Error validating access token.", exc_info=True, extra=extra) raise AuthTokenError(self) else: log("debug", "Found user data for token %s", sanitize_log_data(access_token), extra={"data": data}) return data
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" access_token = None expires = None if 'code' in self.data: state = self.validate_state() url = ACCESS_TOKEN + urlencode({ 'client_id': backend_setting(self, self.SETTINGS_KEY_NAME), 'redirect_uri': self.get_redirect_uri(state), 'client_secret': backend_setting(self, self.SETTINGS_SECRET_NAME), 'code': self.data['code'] }) try: response = cgi.parse_qs(dsa_urlopen(url).read()) except HTTPError: raise AuthFailed( self, 'There was an error authenticating ' 'the app') access_token = response['access_token'][0] if 'expires' in response: expires = response['expires'][0] if 'signed_request' in self.data: response = load_signed_request( self.data.get('signed_request'), backend_setting(self, self.SETTINGS_SECRET_NAME)) if response is not None: access_token = response.get('access_token') or \ response.get('oauth_token') or \ self.data.get('access_token') if 'expires' in response: expires = response['expires'] if access_token: data = self.user_data(access_token) if not isinstance(data, dict): # From time to time Facebook responds back a JSON with just # False as value, the reason is still unknown, but since the # data is needed (it contains the user ID used to identify the # account on further logins), this app cannot allow it to # continue with the auth process. raise AuthUnknownError( self, 'An error ocurred while ' 'retrieving users Facebook ' 'data') data['access_token'] = access_token # expires will not be part of response if offline access # premission was requested if expires: data['expires'] = expires kwargs.update({ 'auth': self, 'response': data, self.AUTH_BACKEND.name: True }) return authenticate(*args, **kwargs) else: if self.data.get('error') == 'access_denied': raise AuthCanceled(self) else: raise AuthException(self)
def enabled(cls): """Return backend enabled status by checking basic settings""" return backend_setting(cls, cls.SETTINGS_KEY_NAME) and \ backend_setting(cls, cls.SETTINGS_SECRET_NAME)
def get_settings(self): client_key = backend_setting(self, self.SETTINGS_KEY_NAME) client_secret = backend_setting(self, self.SETTINGS_SECRET_NAME) public_key = backend_setting(self, self.SETTINGS_PUBLIC_NAME) return client_key, client_secret, public_key
def get_scope(self): return backend_setting(self, 'ODNOKLASSNIKI_OAUTH2_EXTRA_SCOPE', [])
def complete_process(request, backend, *args, **kwargs): """Authentication complete process""" # pop redirect value before the session is trashed on login() redirect_value = request.session.get(REDIRECT_FIELD_NAME, '') user = auth_complete(request, backend, *args, **kwargs) if isinstance(user, HttpResponse): return user if not user and request.user.is_authenticated(): return HttpResponseRedirect(redirect_value) if user: # copy the profile image if user.social_user.provider == 'facebook': picture_page = "https://graph.facebook.com/"+user.username+"/picture?type=square" if user.social_user.provider == 'twitter': picture_page = "http://api.twitter.com/1/users/profile_image?screen_name="+user.username+"&size=normal" if user.social_user.provider == 'yahoo': picture_page = "http://img.msg.yahoo.com/avatar.php?yids="+user.username if user.social_user.provider == 'google': picture_page = None if picture_page: opener1 = urllib2.build_opener() page1 = opener1.open(picture_page) my_picture = page1.read() filename = core.__path__[0] + '/static/photos/profile/'+ user.username fout = open(filename, "wb") fout.write(my_picture) fout.close() if getattr(user, 'is_active', True): # catch is_new flag before login() might reset the instance is_new = getattr(user, 'is_new', False) login(request, user) # user.social_user is the used UserSocialAuth instance defined # in authenticate process social_user = user.social_user if redirect_value: request.session[REDIRECT_FIELD_NAME] = redirect_value or \ DEFAULT_REDIRECT if setting('SOCIAL_AUTH_SESSION_EXPIRATION', True): # Set session expiration date if present and not disabled by # setting. Use last social-auth instance for current provider, # users can associate several accounts with a same provider. expiration = social_user.expiration_datetime() if expiration: try: request.session.set_expiry(expiration) except OverflowError: # Handle django time zone overflow, set default expiry. request.session.set_expiry(None) # store last login backend name in session key = setting('SOCIAL_AUTH_LAST_LOGIN', 'social_auth_last_login_backend') request.session[key] = social_user.provider # Remove possible redirect URL from session, if this is a new # account, send him to the new-users-page if defined. new_user_redirect = backend_setting(backend, 'SOCIAL_AUTH_NEW_USER_REDIRECT_URL') if new_user_redirect and is_new: url = new_user_redirect else: url = redirect_value or \ backend_setting(backend, 'SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \ DEFAULT_REDIRECT else: url = backend_setting(backend, 'SOCIAL_AUTH_INACTIVE_USER_URL', LOGIN_ERROR_URL) else: msg = setting('LOGIN_ERROR_MESSAGE', None) if msg: messages.error(request, msg) url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL) return HttpResponse("<script type='text/javascript'> window.close(); window.opener.refreshPage(); </script>");
def complete_process(request, backend, *args, **kwargs): """Authentication complete process""" # pop redirect value before the session is trashed on login() redirect_value = request.session.get(REDIRECT_FIELD_NAME, '') user = auth_complete(request, backend, *args, **kwargs) if isinstance(user, HttpResponse): return user if not user and request.user.is_authenticated(): return HttpResponseRedirect(redirect_value) if user: # copy the profile image if user.social_user.provider == 'facebook': picture_page = "https://graph.facebook.com/" + user.username + "/picture?type=square" if user.social_user.provider == 'twitter': picture_page = "http://api.twitter.com/1/users/profile_image?screen_name=" + user.username + "&size=normal" if user.social_user.provider == 'yahoo': picture_page = "http://img.msg.yahoo.com/avatar.php?yids=" + user.username if user.social_user.provider == 'google': picture_page = None if picture_page: opener1 = urllib2.build_opener() page1 = opener1.open(picture_page) my_picture = page1.read() filename = core.__path__[ 0] + '/static/photos/profile/' + user.username fout = open(filename, "wb") fout.write(my_picture) fout.close() if getattr(user, 'is_active', True): # catch is_new flag before login() might reset the instance is_new = getattr(user, 'is_new', False) login(request, user) # user.social_user is the used UserSocialAuth instance defined # in authenticate process social_user = user.social_user if redirect_value: request.session[REDIRECT_FIELD_NAME] = redirect_value or \ DEFAULT_REDIRECT if setting('SOCIAL_AUTH_SESSION_EXPIRATION', True): # Set session expiration date if present and not disabled by # setting. Use last social-auth instance for current provider, # users can associate several accounts with a same provider. expiration = social_user.expiration_datetime() if expiration: try: request.session.set_expiry(expiration) except OverflowError: # Handle django time zone overflow, set default expiry. request.session.set_expiry(None) # store last login backend name in session key = setting('SOCIAL_AUTH_LAST_LOGIN', 'social_auth_last_login_backend') request.session[key] = social_user.provider # Remove possible redirect URL from session, if this is a new # account, send him to the new-users-page if defined. new_user_redirect = backend_setting( backend, 'SOCIAL_AUTH_NEW_USER_REDIRECT_URL') if new_user_redirect and is_new: url = new_user_redirect else: url = redirect_value or \ backend_setting(backend, 'SOCIAL_AUTH_LOGIN_REDIRECT_URL') or \ DEFAULT_REDIRECT else: url = backend_setting(backend, 'SOCIAL_AUTH_INACTIVE_USER_URL', LOGIN_ERROR_URL) else: msg = setting('LOGIN_ERROR_MESSAGE', None) if msg: messages.error(request, msg) url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL) return HttpResponse( "<script type='text/javascript'> window.close(); window.opener.refreshPage(); </script>" )
def enabled(cls): """Return backend enabled status by checking basic settings""" return backend_setting(cls, cls.SETTINGS_KEY_NAME) and backend_setting(cls, cls.SETTINGS_SECRET_NAME)
def auth_complete(self, *args, **kwargs): """Completes loging process, must return user instance""" access_token = None expires = None if "code" in self.data: state = self.validate_state() url = ACCESS_TOKEN + urlencode( { "client_id": backend_setting(self, self.SETTINGS_KEY_NAME), "redirect_uri": self.get_redirect_uri(state), "client_secret": backend_setting(self, self.SETTINGS_SECRET_NAME), "code": self.data["code"], } ) try: response = cgi.parse_qs(dsa_urlopen(url).read()) except HTTPError: raise AuthFailed(self, "There was an error authenticating " "the app") access_token = response["access_token"][0] if "expires" in response: expires = response["expires"][0] if "signed_request" in self.data: response = load_signed_request( self.data.get("signed_request"), backend_setting(self, self.SETTINGS_SECRET_NAME) ) if response is not None: access_token = ( response.get("access_token") or response.get("oauth_token") or self.data.get("access_token") ) if "expires" in response: expires = response["expires"] if access_token: data = self.user_data(access_token) if not isinstance(data, dict): # From time to time Facebook responds back a JSON with just # False as value, the reason is still unknown, but since the # data is needed (it contains the user ID used to identify the # account on further logins), this app cannot allow it to # continue with the auth process. raise AuthUnknownError(self, "An error ocurred while " "retrieving users Facebook " "data") data["access_token"] = access_token # expires will not be part of response if offline access # premission was requested if expires: data["expires"] = expires kwargs.update({"auth": self, "response": data, self.AUTH_BACKEND.name: True}) return authenticate(*args, **kwargs) else: if self.data.get("error") == "access_denied": raise AuthCanceled(self) else: raise AuthException(self)