def auth_process(request, backend): """Authenticate using social backend""" data = request.POST if request.method == 'POST' else request.GET # Save extra data into session. for field_name in setting('SOCIAL_AUTH_FIELDS_STORED_IN_SESSION', []): if field_name in data: request.session[field_name] = data[field_name] # Save any defined next value into session if REDIRECT_FIELD_NAME in data: # Check and sanitize a user-defined GET/POST next field value redirect = data[REDIRECT_FIELD_NAME] if setting('SOCIAL_AUTH_SANITIZE_REDIRECTS', True): redirect = sanitize_redirect(request.get_host(), redirect) request.session[REDIRECT_FIELD_NAME] = (redirect or resolve_url(DEFAULT_REDIRECT)) # Clean any partial pipeline info before starting the process clean_partial_pipeline(request) if backend.uses_redirect: return HttpResponseRedirect(backend.auth_url()) else: return HttpResponse(backend.auth_html(), content_type='text/html;charset=UTF-8')
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 \ resolve_url(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 = resolve_url(backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL)) elif isinstance(user, HttpResponse): return user else: url = redirect_value or \ backend_setting(backend, 'SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL') or \ DEFAULT_REDIRECT return HttpResponseRedirect(resolve_url(url))
def test_login_succeful(self): """ """ response = self.client.get('http://%s%s' % (self.SERVER_NAME, self.reverse('socialauth_begin', 'facebook'))) # social_auth must redirect to service page self.assertEqual(response.status_code, 302) # Open first redirect page, it contains user login form because # we don't have cookie to send to twitter parser = FormParserByID('login_form') content = self.get_content(response['Location'], use_cookies=True) parser.feed(content) auth = {'email': self.user, 'pass': self.passwd} # Check that action and values were loaded properly self.assertTrue(parser.action) self.assertTrue(parser.values) # Post login form, will return authorization or redirect page parser.values.update(auth) redirect = self.get_redirect(parser.action, parser.values, use_cookies=True) # If page contains a form#login_form, then we are in the app # authorization page because the app is not authorized yet, # otherwise the app already gained permission and twitter sends # a page that redirects to redirect_url if 'login_form' in content: # authorization form post, returns redirect_page parser = FormParserByID('login_form') parser.feed(content) self.assertTrue(parser.action) self.assertTrue(parser.values) parser.values.update(auth) redirect = self.get_redirect(parser.action, parser.values, use_cookies=True) redirect_page = redirect.read() else: redirect = self.get_redirect(redirect.headers['Location'], use_cookies=True) redirect_page = redirect.read() if 'uiserver_form' in redirect_page: # authorization form post, returns redirect_page parser = FormParserByID('uiserver_form') parser.feed(redirect_page) self.assertTrue(parser.action) self.assertTrue(parser.values) parser.values.update(auth) redirect = self.get_redirect(parser.action, parser.values, use_cookies=True) self.assertTrue(resolve_url(setting('LOGIN_REDIRECT_URL')) in self.make_relative(redirect.headers['Location']))
def test_login_successful(self): response = self.client.get(self.reverse('socialauth_begin', 'twitter')) # social_auth must redirect to service page self.assertEqual(response.status_code, 302) # Open first redirect page, it contains user login form because # we don't have cookie to send to twitter login_content = self.get_content(response['Location']) parser = FormParserByID('oauth_form') parser.feed(login_content) auth = {'session[username_or_email]': self.user, 'session[password]': self.passwd} # Check that action and values were loaded properly self.assertTrue(parser.action) self.assertTrue(parser.values) # Post login form, will return authorization or redirect page parser.values.update(auth) content = self.get_content(parser.action, data=parser.values) # If page contains a form#login_form, then we are in the app # authorization page because the app is not authorized yet, # otherwise the app already gained permission and twitter sends # a page that redirects to redirect_url if 'login_form' in content: # authorization form post, returns redirect_page parser = FormParserByID('login_form').feed(content) self.assertTrue(parser.action) self.assertTrue(parser.values) parser.values.update(auth) redirect_page = self.get_content(parser.action, data=parser.values) else: redirect_page = content parser = RefreshParser() parser.feed(redirect_page) self.assertTrue(parser.value) response = self.client.get(self.make_relative(parser.value)) self.assertEqual(response.status_code, 302) location = self.make_relative(response['Location']) login_redirect = resolve_url(setting('LOGIN_REDIRECT_URL')) self.assertTrue(location == login_redirect)
def test_login_succeful(self): if self.name not in settings.SOCIAL_AUTH_ENABLED_BACKENDS: self.skipTest("Google OpenID is not enabled") response = self.client.get(self.reverse("socialauth_begin", "google")) parser = FormParserByID("openid_message") parser.feed(response.content) # Check that action and values were loaded properly self.assertTrue(parser.action) self.assertTrue(parser.values) content = self.get_content(parser.action, parser.values, use_cookies=True) parser = FormParserByID("gaia_loginform") parser.feed(content) auth = {"Email": self.user, "Passwd": self.passwd} parser.values.update(auth) # Check that action and values were loaded properly self.assertTrue(parser.action) self.assertTrue(parser.values) content = self.get_content(parser.action, parser.values, use_cookies=True) parser = RefreshParser() parser.feed(content) # approved? result = self.get_redirect(parser.value, use_cookies=True) if result.headers.get("Location", ""): # approved? # damn, google has a hell of redirects :-( result = self.get_redirect(result.headers["Location"], use_cookies=True) result = self.get_redirect(result.headers["Location"], use_cookies=True) result = self.get_redirect(result.headers["Location"], use_cookies=True) # app was not approved if self.SERVER_NAME not in result.headers.get("Location", ""): content = self.get_content(parser.value, use_cookies=True) parser = FormParser() parser.feed(content) parser.values["submit_true"] = "yes" parser.values["remember_choices"] = "yes" result = self.get_redirect(parser.action, parser.values, use_cookies=True) response = self.client.get(self.make_relative(result.headers["Location"])) self.assertTrue(resolve_url(setting("LOGIN_REDIRECT_URL")) in self.make_relative(response["Location"]))
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, '') or \ request.REQUEST.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) msg = None 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 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 request.session['social_auth_last_login_backend'] = \ 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: msg = setting('SOCIAL_AUTH_INACTIVE_USER_MESSAGE', None) url = backend_setting(backend, 'SOCIAL_AUTH_INACTIVE_USER_URL', LOGIN_ERROR_URL) else: msg = setting('LOGIN_ERROR_MESSAGE', None) url = backend_setting(backend, 'LOGIN_ERROR_URL', LOGIN_ERROR_URL) if msg: messages.error(request, msg) url = resolve_url(url) if redirect_value and redirect_value != url: redirect_value = quote(redirect_value) if '?' in url: url += '&%s=%s' % (REDIRECT_FIELD_NAME, redirect_value) else: url += '?%s=%s' % (REDIRECT_FIELD_NAME, redirect_value) return HttpResponseRedirect(url)
def get_redirect_uri(self, request, exception): if self.backend is not None: return resolve_url(backend_setting(self.backend, 'SOCIAL_AUTH_BACKEND_ERROR_URL') or settings.LOGIN_ERROR_URL) return resolve_url(settings.LOGIN_ERROR_URL)