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 }) 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)
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 occurred 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)
def disconnect(request, backend, association_id=None): """Disconnects given backend from current logged in user.""" backend.disconnect(request.user, association_id) url = request.POST.get(REDIRECT_FIELD_NAME, '') or \ backend_setting(backend, 'SOCIAL_AUTH_DISCONNECT_REDIRECT_URL') or \ DEFAULT_REDIRECT 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 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 = json.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 = urlparse.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 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: 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 HttpResponseRedirect(url)
def auth_complete(self, *args, **kwargs): """Completes logging 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 = urlparse.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 occurred while retrieving users Facebook data') data['access_token'] = access_token # expires will not be part of response if offline access # permission 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)