mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-02 09:13:25 +02:00
Implement VIP table and fix 401 login bug
This commit is contained in:
parent
7077519837
commit
510da21934
11 changed files with 175 additions and 1 deletions
|
@ -33,6 +33,10 @@ class AuthenticationFailed(OIDCException):
|
|||
friendly_message = "This login attempt didn't work."
|
||||
|
||||
|
||||
class NoStateDefined(OIDCException):
|
||||
friendly_message = "The session state is None."
|
||||
|
||||
|
||||
class InternalError(OIDCException):
|
||||
status = status.INTERNAL_SERVER_ERROR
|
||||
friendly_message = "The system broke while trying to log you in."
|
||||
|
|
|
@ -183,6 +183,8 @@ class Client(oic.Client):
|
|||
if authn_response["state"] != session.get("state", None):
|
||||
# this most likely means the user's Django session vanished
|
||||
logger.error("Received state not the same as expected for %s" % state)
|
||||
if session.get("state", None) is None:
|
||||
raise o_e.NoStateDefined()
|
||||
raise o_e.AuthenticationFailed(locator=state)
|
||||
|
||||
if self.behaviour.get("response_type") == "code":
|
||||
|
@ -272,6 +274,11 @@ class Client(oic.Client):
|
|||
|
||||
super(Client, self).store_response(resp, info)
|
||||
|
||||
def get_default_acr_value(self):
|
||||
"""returns the acr_value from settings
|
||||
this helper function is called from djangooidc views"""
|
||||
return self.behaviour.get("acr_value")
|
||||
|
||||
def get_step_up_acr_value(self):
|
||||
"""returns the step_up_acr_value from settings
|
||||
this helper function is called from djangooidc views"""
|
||||
|
|
|
@ -3,6 +3,8 @@ from unittest.mock import MagicMock, patch
|
|||
from django.http import HttpResponse
|
||||
from django.test import Client, TestCase, RequestFactory
|
||||
from django.urls import reverse
|
||||
|
||||
from djangooidc.exceptions import NoStateDefined
|
||||
from ..views import login_callback
|
||||
|
||||
from .common import less_console_noise
|
||||
|
@ -17,6 +19,9 @@ class ViewsTest(TestCase):
|
|||
def say_hi(*args):
|
||||
return HttpResponse("Hi")
|
||||
|
||||
def create_acr(*args):
|
||||
return "any string"
|
||||
|
||||
def user_info(*args):
|
||||
return {
|
||||
"sub": "TEST",
|
||||
|
@ -34,6 +39,7 @@ class ViewsTest(TestCase):
|
|||
callback_url = reverse("openid_login_callback")
|
||||
# mock
|
||||
mock_client.create_authn_request.side_effect = self.say_hi
|
||||
mock_client.get_default_acr_value.side_effect = self.create_acr
|
||||
# test
|
||||
response = self.client.get(reverse("login"), {"next": callback_url})
|
||||
# assert
|
||||
|
@ -53,6 +59,19 @@ class ViewsTest(TestCase):
|
|||
self.assertTemplateUsed(response, "500.html")
|
||||
self.assertIn("Server error", response.content.decode("utf-8"))
|
||||
|
||||
def test_callback_with_no_session_state(self, mock_client):
|
||||
"""If the local session is None (ie the server restarted while user was logged out),
|
||||
we do not throw an exception. Rather, we attempt to login again."""
|
||||
# mock
|
||||
mock_client.get_default_acr_value.side_effect = self.create_acr
|
||||
mock_client.callback.side_effect = NoStateDefined()
|
||||
# test
|
||||
with less_console_noise():
|
||||
response = self.client.get(reverse("openid_login_callback"))
|
||||
# assert
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.url, "/")
|
||||
|
||||
def test_login_callback_reads_next(self, mock_client):
|
||||
# setup
|
||||
session = self.client.session
|
||||
|
|
|
@ -55,6 +55,10 @@ def error_page(request, error):
|
|||
|
||||
def openid(request):
|
||||
"""Redirect the user to an authentication provider (OP)."""
|
||||
|
||||
# If the session reset because of a server restart, attempt to login again
|
||||
request.session["acr_value"] = CLIENT.get_default_acr_value()
|
||||
|
||||
request.session["next"] = request.GET.get("next", "/")
|
||||
|
||||
try:
|
||||
|
@ -78,9 +82,13 @@ def login_callback(request):
|
|||
if user:
|
||||
login(request, user)
|
||||
logger.info("Successfully logged in user %s" % user)
|
||||
# Double login bug?
|
||||
return redirect(request.session.get("next", "/"))
|
||||
else:
|
||||
raise o_e.BannedUser()
|
||||
except o_e.NoStateDefined as nsd_err:
|
||||
logger.debug(f"No State Defined: {nsd_err}")
|
||||
return redirect(request.session.get("next", "/"))
|
||||
except Exception as err:
|
||||
return error_page(request, err)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue