def post(self, request): authenticated = False if 'challenge' in request.DATA and 'response' in request.DATA: try: interface = Authenticator.objects.get_interface( request.user, 'u2f') if not interface.is_enrolled: raise LookupError() challenge = json.loads(request.DATA['challenge']) response = json.loads(request.DATA['response']) authenticated = interface.validate_response( request, challenge, response) except ValueError: pass except LookupError: pass else: authenticated = auth.authenticate( username=request.user.email, password=request.DATA.get('password')) if authenticated: grant_sudo_privileges(request._request) return Response(status=status.HTTP_204_NO_CONTENT) # UI treats 401s by redirecting, this 401 should be ignored return Response({'detail': { 'code': 'ignore' }}, status=status.HTTP_401_UNAUTHORIZED)
def post(self, request): authenticated = False if 'challenge' in request.DATA and 'response' in request.DATA: try: interface = Authenticator.objects.get_interface( request.user, 'u2f') if not interface.is_enrolled: raise LookupError() challenge = json.loads(request.DATA['challenge']) response = json.loads(request.DATA['response']) authenticated = interface.validate_response( request, challenge, response) except ValueError: pass except LookupError: pass else: authenticated = auth.authenticate( username=request.user.email, password=request.DATA.get('password')) if authenticated: grant_sudo_privileges(request._request) return Response(status=status.HTTP_204_NO_CONTENT) return Response({'allowFail': True}, content_type="application/json", status=status.HTTP_401_UNAUTHORIZED)
def sudo(request, template_name='sudo/sudo.html', extra_context=None): """ The default view for the sudo mode page. The role of this page is to prompt the user for their password again, and if successful, redirect them back to ``next``. """ redirect_to = request.GET.get(REDIRECT_FIELD_NAME, REDIRECT_URL) # Make sure we're not redirecting to other sites if not is_safe_url(url=redirect_to, host=request.get_host()): redirect_to = resolve_url(REDIRECT_URL) if request.is_sudo(): return HttpResponseRedirect(redirect_to) form = SudoForm(request.user, request.POST or None) if request.method == 'POST': if form.is_valid(): grant_sudo_privileges(request) return HttpResponseRedirect(redirect_to) context = { 'form': form, REDIRECT_FIELD_NAME: redirect_to, } if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def grant_sudo_privileges(self, request, redirect_to): grant_sudo_privileges(request) # Restore the redirect destination from the GET request redirect_to = request.session.pop(REDIRECT_TO_FIELD_NAME, redirect_to) # Double check we're not redirecting to other sites if not is_safe_url(url=redirect_to, host=request.get_host()): redirect_to = resolve_url(REDIRECT_URL) return HttpResponseRedirect(redirect_to)
def test_process_response_sudo_revoked_without_cookie(self): self.login() self.middleware.process_request(self.request) grant_sudo_privileges(self.request) revoke_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 0)
def test_process_response_sets_secure_cookie(self): self.login() self.request.is_secure = lambda: True self.middleware.process_request(self.request) grant_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] self.assertTrue(self.request.is_secure()) self.assertTrue(sudo['secure'])
def test_process_response_sets_secure_cookie(self): self.login() self.request.is_secure = lambda: True self.middleware.process_request(self.request) grant_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] self.assertTrue(self.request.is_secure()) self.assertTrue(sudo["secure"])
def login_as(self, user): user.backend = settings.AUTHENTICATION_BACKENDS[0] engine = import_module(settings.SESSION_ENGINE) request = HttpRequest() if self.client.session: request.session = self.client.session else: request.session = engine.SessionStore() login(request, user) request.user = user sudo_token = grant_sudo_privileges(request) # Save the session values. request.session.save() # Set the cookie to represent the session. session_cookie = settings.SESSION_COOKIE_NAME self.client.cookies[session_cookie] = request.session.session_key cookie_data = { 'max-age': None, 'path': '/', 'domain': settings.SESSION_COOKIE_DOMAIN, 'secure': settings.SESSION_COOKIE_SECURE or None, 'expires': None, } self.client.cookies[session_cookie].update(cookie_data) self.client.cookies[SUDO_COOKIE_NAME] = sudo_token
def test_process_response_sudo_revoked_removes_cookie(self): self.login() self.middleware.process_request(self.request) grant_sudo_privileges(self.request) self.request.COOKIES[COOKIE_NAME] = self.request._sudo_token revoke_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] # Deleting a cookie is just setting it's value to empty # and telling it to expire self.assertEqual(sudo.key, COOKIE_NAME) self.assertFalse(sudo.value) self.assertEqual(sudo['max-age'], 0)
def test_process_response_sudo_revoked_removes_cookie(self): self.login() self.middleware.process_request(self.request) grant_sudo_privileges(self.request) self.request.COOKIES[COOKIE_NAME] = self.request._sudo_token revoke_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] # Deleting a cookie is just setting it's value to empty # and telling it to expire self.assertEqual(sudo.key, COOKIE_NAME) self.assertFalse(sudo.value) self.assertEqual(sudo["max-age"], 0)
def test_process_response_with_sudo_sets_cookie(self): self.login() self.middleware.process_request(self.request) grant_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] self.assertEqual(sudo.key, COOKIE_NAME) self.assertEqual(sudo.value, self.request._sudo_token) self.assertEqual(sudo['max-age'], self.request._sudo_max_age) self.assertTrue(sudo['httponly']) # Asserting that these are insecure together explicitly # since it's a big deal to not f**k up self.assertFalse(self.request.is_secure()) self.assertFalse(sudo['secure']) # insecure request
def test_process_response_with_sudo_sets_cookie(self): self.login() self.middleware.process_request(self.request) grant_sudo_privileges(self.request) response = self.middleware.process_response(self.request, HttpResponse()) morsels = list(response.cookies.items()) self.assertEqual(len(morsels), 1) self.assertEqual(morsels[0][0], COOKIE_NAME) _, sudo = morsels[0] self.assertEqual(sudo.key, COOKIE_NAME) self.assertSignedCookieEqual(sudo.value, self.request._sudo_token) self.assertEqual(sudo["max-age"], self.request._sudo_max_age) self.assertTrue(sudo["httponly"]) # Asserting that these are insecure together explicitly # since it's a big deal to not bungle. self.assertFalse(self.request.is_secure()) self.assertFalse(sudo["secure"]) # insecure request
def test_grant_token_default_max_age(self): self.login() token = grant_sudo_privileges(self.request) self.assertIsNotNone(token) self.assertRequestHasToken(self.request, COOKIE_AGE)
def test_grant_token_not_logged_in(self): with self.assertRaises(ValueError): grant_sudo_privileges(self.request)
def test_grant_token_explicit_max_age(self): self.login() token = grant_sudo_privileges(self.request, 60) self.assertIsNotNone(token) self.assertRequestHasToken(self.request, 60)
def test_without_user(self): delattr(self.request, 'user') token = grant_sudo_privileges(self.request) self.assertIsNone(token)
def test_revoke_sudo_privileges(self): self.login() grant_sudo_privileges(self.request) revoke_sudo_privileges(self.request) self.assertRequestNotSudo(self.request)
def test_granted(self): self.login() grant_sudo_privileges(self.request) self.assertTrue(has_sudo_privileges(self.request))
def test_revoked(self): self.login() grant_sudo_privileges(self.request) revoke_sudo_privileges(self.request) self.assertFalse(has_sudo_privileges(self.request))
def test_without_user(self): delattr(self.request, "user") token = grant_sudo_privileges(self.request) self.assertIsNone(token)
def test_user_logged_out(self): self.login() grant_sudo_privileges(self.request) self.assertTrue(has_sudo_privileges(self.request)) user_logged_out.send_robust(sender=User, request=self.request) self.assertFalse(has_sudo_privileges(self.request))
def grant(sender, request, **kwargs): """ Automatically grant sudo privileges when logging in. """ grant_sudo_privileges(request)