Linting and fix unit tests

This commit is contained in:
zandercymatics 2024-05-16 14:15:42 -06:00
parent 733cc53f91
commit 7681cc4f0b
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
4 changed files with 65 additions and 68 deletions

View file

@ -117,26 +117,7 @@ class Client(oic.Client):
logger.debug("request args: %s" % request_args)
try:
# prepare the request for sending
cis = self.construct_AuthorizationRequest(request_args=request_args)
logger.debug("request: %s" % cis)
# obtain the url and headers from the prepared request
url, body, headers, cis = self.uri_and_body(
AuthorizationRequest,
cis,
method="GET",
request_args=request_args,
)
logger.debug("body: %s" % body)
logger.debug("URL: %s" % url)
logger.debug("headers: %s" % headers)
except Exception as err:
logger.error(err)
logger.error("Failed to prepare request for %s" % state)
raise o_e.InternalError(locator=state)
url, headers = self._prepare_authn_request(request_args, state) # C901 too complex
try:
# create the redirect object
@ -159,6 +140,35 @@ class Client(oic.Client):
request_args["vtr"] = self.get_vtr_value()
request_args["vtm"] = self.get_vtm_value()
def _prepare_authn_request(self, request_args, state):
"""
Constructs an authorization request. Then, assembles the url, body, headers, and cis.
Returns the assembled url and associated header information: `(url, headers)`
"""
try:
# prepare the request for sending
cis = self.construct_AuthorizationRequest(request_args=request_args)
logger.debug("request: %s" % cis)
# obtain the url and headers from the prepared request
url, body, headers, cis = self.uri_and_body(
AuthorizationRequest,
cis,
method="GET",
request_args=request_args,
)
logger.debug("body: %s" % body)
logger.debug("URL: %s" % url)
logger.debug("headers: %s" % headers)
except Exception as err:
logger.error(err)
logger.error("Failed to prepare request for %s" % state)
raise o_e.InternalError(locator=state)
return (url, headers)
def callback(self, unparsed_response, session):
"""Step 3: Receive OP's response, request an access token, and user info."""
logger.debug("Processing the OpenID Connect callback response...")
@ -311,7 +321,7 @@ class Client(oic.Client):
"""Returns the vtm value from settings.
This helper function is called from djangooidc views."""
return self.behaviour.get("vtm")
def get_vtr_value(self, cleaned=True):
"""Returns the vtr value from settings.
This helper function is called from djangooidc views."""

View file

@ -184,7 +184,7 @@ class ViewsTest(TestCase):
# patch that the request does not require step up auth
# TEST
# test the login callback url
with patch("djangooidc.views._requires_step_up_auth", return_value=False):
with patch("djangooidc.views._requires_biometric_auth", return_value=False):
response = self.client.get(reverse("openid_login_callback"))
# ASSERTIONS
# assert the redirect url is the same as the 'next' value set in session
@ -224,7 +224,7 @@ class ViewsTest(TestCase):
# mock that callback returns user_info; this is the expected behavior
mock_client.callback.side_effect = self.user_info
# patch that the request does not require step up auth
with patch("djangooidc.views._requires_step_up_auth", return_value=False):
with patch("djangooidc.views._requires_biometric_auth", return_value=False):
with patch("djangooidc.views._initialize_client") as mock_init_client:
with patch("djangooidc.views._client_is_none") as mock_client_is_none:
# mock the client to initially be None
@ -252,7 +252,7 @@ class ViewsTest(TestCase):
# mock that callback returns user_info; this is the expected behavior
mock_client.callback.side_effect = self.user_info
# patch that the request does not require step up auth
with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch(
with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch(
"djangooidc.views._initialize_client"
) as mock_init_client:
with patch("djangooidc.views._client_is_none", return_value=True):
@ -285,7 +285,7 @@ class ViewsTest(TestCase):
# mock that callback returns user_info; this is the expected behavior
mock_client.callback.side_effect = self.user_info
# patch that the request does not require step up auth
with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch(
with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch(
"djangooidc.views._initialize_client"
) as mock_init_client:
with patch("djangooidc.views._client_is_none", return_value=True):
@ -319,7 +319,7 @@ class ViewsTest(TestCase):
td, _ = TransitionDomain.objects.get_or_create(username="test@example.com", domain_name="test123.gov")
# patch that the request does not require step up auth
with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch(
with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch(
"djangooidc.views._initialize_client"
) as mock_init_client:
with patch("djangooidc.views._client_is_none", return_value=True):
@ -353,7 +353,7 @@ class ViewsTest(TestCase):
vip, _ = VerifiedByStaff.objects.get_or_create(email="test@example.com")
# patch that the request does not require step up auth
with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch(
with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch(
"djangooidc.views._initialize_client"
) as mock_init_client:
with patch("djangooidc.views._client_is_none", return_value=True):
@ -374,7 +374,7 @@ class ViewsTest(TestCase):
self.assertEqual(created_user.verification_type, User.VerificationTypeChoices.VERIFIED_BY_STAFF)
def test_login_callback_no_step_up_auth(self, mock_client):
"""Walk through login_callback when _requires_step_up_auth returns False
"""Walk through login_callback when _requires_biometric_auth returns False
and assert that we have a redirect to /"""
with less_console_noise():
# SETUP
@ -386,59 +386,33 @@ class ViewsTest(TestCase):
# patch that the request does not require step up auth
# TEST
# test the login callback url
with patch("djangooidc.views._requires_step_up_auth", return_value=False):
with patch("djangooidc.views._requires_biometric_auth", return_value=False):
response = self.client.get(reverse("openid_login_callback"))
# ASSERTIONS
# assert that redirect is to / when no 'next' is set
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/")
def test_login_callback_requires_step_up_auth(self, mock_client):
"""Invoke login_callback passing it a request when _requires_step_up_auth returns True
and assert that session is updated and create_authn_request (mock) is called."""
with less_console_noise():
# MOCK
# Configure the mock to return an expected value for get_step_up_acr_value
mock_client.return_value.get_step_up_acr_value.return_value = "step_up_acr_value"
# Create a mock request
request = self.factory.get("/some-url")
request.session = {"acr_value": ""}
# Ensure that the CLIENT instance used in login_callback is the mock
# patch _requires_step_up_auth to return True
with patch("djangooidc.views._requires_step_up_auth", return_value=True), patch(
"djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock()
) as mock_create_authn_request:
# TEST
# test the login callback
login_callback(request)
# ASSERTIONS
# create_authn_request only gets called when _requires_step_up_auth is True
# and it changes this acr_value in request.session
# Assert that acr_value is no longer empty string
self.assertNotEqual(request.session["acr_value"], "")
# And create_authn_request was called again
mock_create_authn_request.assert_called_once()
def test_login_callback_does_not_requires_step_up_auth(self, mock_client):
"""Invoke login_callback passing it a request when _requires_step_up_auth returns False
def test_login_callback_does_not_requires_biometric_auth(self, mock_client):
"""Invoke login_callback passing it a request when _requires_biometric_auth returns False
and assert that session is not updated and create_authn_request (mock) is not called.
Possibly redundant with test_login_callback_requires_step_up_auth"""
Possibly redundant with test_login_callback_requires_biometric_auth"""
with less_console_noise():
# MOCK
# Create a mock request
request = self.factory.get("/some-url")
request.session = {"acr_value": ""}
# Ensure that the CLIENT instance used in login_callback is the mock
# patch _requires_step_up_auth to return False
with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch(
# patch _requires_biometric_auth to return False
with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch(
"djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock()
) as mock_create_authn_request:
# TEST
# test the login callback
login_callback(request)
# ASSERTIONS
# create_authn_request only gets called when _requires_step_up_auth is True
# create_authn_request only gets called when _requires_biometric_auth is True
# and it changes this acr_value in request.session
# Assert that acr_value is NOT updated by testing that it is still an empty string
self.assertEqual(request.session["acr_value"], "")
@ -454,7 +428,7 @@ class ViewsTest(TestCase):
mock_client.callback.side_effect = self.user_info
mock_auth.return_value = None
# TEST
with patch("djangooidc.views._requires_step_up_auth", return_value=False):
with patch("djangooidc.views._requires_biometric_auth", return_value=False):
response = self.client.get(reverse("openid_login_callback"))
# ASSERTIONS
self.assertEqual(response.status_code, 401)

View file

@ -96,7 +96,7 @@ def login_callback(request):
# if not satisfied, redirect user to login requiring biometric auth
# Tests for the presence of the vtm/vtr values in the userinfo object.
# If they are there, then we can set a flag in our session for tracking purposes.
# If they are there, then we can set a flag in our session for tracking purposes.
needs_biometric_validation = _requires_biometric_auth(userinfo)
request.session["needs_biometric_validation"] = needs_biometric_validation
@ -145,9 +145,22 @@ def login_callback(request):
return error_page(request, err)
def _requires_biometric_auth(userinfo):
"""if User.needs_identity_verification and step_up_acr_value not in
ial returned from callback, return True"""
def _requires_biometric_auth(userinfo) -> bool:
"""
Checks for the presence of the key 'vtm' and 'vtr' in the provided `userinfo` object.
If they are not found, then we call `User.needs_identity_verification()`.
Args:
userinfo (dict): A dictionary of data from the returned user object.
Return Conditions:
If the provided user does not exist in any tables which would preclude them from doing
biometric authentication, then we return True. Otherwise, we return False.
Alternatively, if 'vtm' and 'vtr' already exist on `userinfo`, then we return False.
"""
uuid = userinfo.get("sub", "")
email = userinfo.get("email", "")
if not userinfo.get("vtm") or not userinfo.get("vtr"):