Skip to content

Commit

Permalink
APM-5429 added product scope tests for different auth levels
Browse files Browse the repository at this point in the history
  • Loading branch information
sophieclayton12-nhs committed Aug 21, 2024
1 parent b15bfde commit 05ca747
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 41 deletions.
12 changes: 4 additions & 8 deletions e2e/tests/logging/test_splunk_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from uuid import uuid4

from e2e.tests.utils.config import MOCK_CIS2_USERNAMES
from e2e.tests.utils.helpers import (
create_client_assertion,
create_subject_token,
Expand All @@ -18,11 +19,6 @@ class TestSplunkLoggingFields:
# We are on our second generation of mock identity provider for
# healthcare_worker access (CIS2). This allows you to log-in using a
# username.
MOCK_CIS2_USERNAMES = {
"aal1": ["656005750110"],
"aal2": ["656005750109"],
"aal3": ["656005750104"],
}

# Create a list of pytest.param for each combination of username and level for combined auth
combined_auth_params = [
Expand Down Expand Up @@ -110,7 +106,7 @@ def test_splunk_fields_for_authorize_endpoint(
assert auth_meta["auth_type"] == "user"
assert auth_meta["grant_type"] == "authorization_code"
assert auth_meta["level"] == "" # level is unknown when hitting /authorize

assert auth_meta["provider"] == provider

auth_user = auth["user"]
Expand Down Expand Up @@ -246,7 +242,7 @@ def test_splunk_fields_for_token_endpoint_authorization_code(
assert auth_meta["auth_type"] == "user"
assert auth_meta["grant_type"] == "authorization_code"
assert auth_meta["level"] == level

assert auth_meta["provider"] == provider

auth_user = auth["user"]
Expand Down Expand Up @@ -411,4 +407,4 @@ def test_splunk_fields_for_token_endpoint_token_exchange_nhs_login(
assert auth_meta["provider"] == "apim-mock-nhs-login"

auth_user = auth["user"]
assert auth_user["user_id"] == "9912003071"
assert auth_user["user_id"] == "9912003071"
13 changes: 4 additions & 9 deletions e2e/tests/oauth/test_authorization_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from urllib import parse

from e2e.tests.utils.response_bank import BANK
from e2e.tests.utils.config import CANARY_API_URL, CANARY_PRODUCT_NAME
from e2e.tests.utils.config import CANARY_API_URL, CANARY_PRODUCT_NAME, MOCK_CIS2_USERNAMES
from e2e.tests.utils.helpers import (
remove_keys,
replace_keys,
Expand All @@ -18,15 +18,10 @@


class TestAuthorizationCode:
"""A test suit to test the token exchange flow"""
"""A test suit to test the authorization code flow"""
# We are on our second generation of mock identity provider for
# healthcare_worker access (CIS2). This allows you to log-in using a
# username.
MOCK_CIS2_USERNAMES = {
"aal1": ["656005750110"],
"aal2": ["656005750109"],
"aal3": ["656005750104"],
}

# Create a list of pytest.param for each combination of username and level for combined auth
combined_auth_params = [
Expand All @@ -42,7 +37,7 @@ class TestAuthorizationCode:
for level, usernames in MOCK_CIS2_USERNAMES.items()
for username in usernames
]

def get_params_from_url(self, url: str) -> dict:
"""Returns all the params and param values from a given url as a dictionary"""
return dict(parse.parse_qsl(parse.urlsplit(url).query))
Expand Down Expand Up @@ -1211,4 +1206,4 @@ def test_nhs_login_refresh_tokens_generated_with_expected_expiry_combined_auth(
Test that refresh tokens generated via NHS Login have an expiry time of 1 hour for combined authentication.
"""
assert _nhsd_apim_auth_token_data["expires_in"] == "599"
assert _nhsd_apim_auth_token_data["refresh_token_expires_in"] == "3599"
assert _nhsd_apim_auth_token_data["refresh_token_expires_in"] == "3599"
7 changes: 1 addition & 6 deletions e2e/tests/oauth/test_backchannel_logout.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@
from typing import Dict, Optional
from uuid import uuid4

from e2e.tests.utils.config import JWT_PRIVATE_KEY_ABSOLUTE_PATH
from e2e.tests.utils.config import JWT_PRIVATE_KEY_ABSOLUTE_PATH, MOCK_CIS2_USERNAMES


class TestBackChannelLogout:
"""A test suite for back-channel logout functionality"""
# We are on our second generation of mock identity provider for
# healthcare_worker access (CIS2). This allows you to log-in using a
# username.
MOCK_CIS2_USERNAMES = {
"aal1": ["656005750110"],
"aal2": ["656005750109"],
"aal3": ["656005750104"],
}

# Create a list of pytest.param for each combination of username and level for combined auth
combined_auth_params = [
Expand Down
7 changes: 1 addition & 6 deletions e2e/tests/oauth/test_token_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from time import time

from e2e.tests.utils.config import CANARY_API_URL, CANARY_PRODUCT_NAME
from e2e.tests.utils.config import CANARY_API_URL, CANARY_PRODUCT_NAME, MOCK_CIS2_USERNAMES
from e2e.tests.utils.helpers import (
change_jwks_url,
create_client_assertion,
Expand All @@ -21,11 +21,6 @@ class TestTokenExchange:
# We are on our second generation of mock identity provider for
# healthcare_worker access (CIS2). This allows you to log-in using a
# username.
MOCK_CIS2_USERNAMES = {
"aal1": ["656005750110"],
"aal2": ["656005750109"],
"aal3": ["656005750104"],
}

# Create a list of pytest.param for each combination of username and level for combined auth
seperate_auth_params = [
Expand Down
100 changes: 88 additions & 12 deletions e2e/tests/product_scopes/test_product_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ def create_client_credentials_token_data(
def create_authorization_code_token_data(
self, client_id, client_secret, callback_url, identity_url, auth_pattern
):
username = "656005750104"
auth_pattern_mock_cis2_usernames_map = {
"cis2_combined_aal1": "656005750110",
"cis2_combined_aal2": "656005750109",
"cis2_combined": "656005750104",
}
username = auth_pattern_mock_cis2_usernames_map.get(auth_pattern, "656005750104")
authorize_params = {
"client_id": client_id,
"redirect_uri": callback_url,
Expand Down Expand Up @@ -106,7 +111,12 @@ def create_token_exchange_token_data(
def hit_authorize_and_callback_endpoints(
self, client_id, callback_url, identity_url, auth_pattern, header_filters
):
username = "656005750104"
auth_pattern_mock_cis2_usernames_map = {
"cis2_combined_aal1": "656005750110",
"cis2_combined_aal2": "656005750109",
"cis2_combined": "656005750104",
}
username = auth_pattern_mock_cis2_usernames_map.get(auth_pattern, "656005750104")
authorize_params = {
"client_id": client_id,
"redirect_uri": callback_url,
Expand Down Expand Up @@ -215,7 +225,21 @@ def hit_authorize_and_callback_endpoints(
[],
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
"cis2_combined",
id="User-restricted-CIS2-combined: one product with valid scope",
id="User-restricted-CIS2-combined: one product with valid scope (authed as aal3 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
[],
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
"cis2_combined_aal2",
id="User-restricted-CIS2-combined: one product with valid scope (authed as aal2 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal1:personal-demographics-service"],
[],
["urn:nhsd:apim:user-nhs-id:aal1:personal-demographics-service"],
"cis2_combined_aal1",
id="User-restricted-CIS2-combined: one product with valid scope (authed as aal1 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
Expand Down Expand Up @@ -377,7 +401,21 @@ def hit_authorize_and_callback_endpoints(
[],
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
"cis2_seperate",
id="User-restricted-CIS2-seperate: one product with valid scope",
id="User-restricted-CIS2-seperate: one product with valid scope (authed as aal3 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
[],
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
"cis2_separate_aal2",
id="User-restricted-CIS2-separate: one product with valid scope (authed as aal2 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal1:personal-demographics-service"],
[],
["urn:nhsd:apim:user-nhs-id:aal1:personal-demographics-service"],
"cis2_separate_aal1",
id="User-restricted-CIS2-separate: one product with valid scope (authed as aal1 user)",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
Expand Down Expand Up @@ -568,15 +606,22 @@ def test_valid_scope_combinations(
token_data=token_data_client_credentials,
private_key=_jwt_keys["private_key_pem"],
)
elif auth_pattern == "cis2_combined" or auth_pattern == "nhs_login_combined":
elif auth_pattern in ["cis2_combined", "cis2_combined_aal2", "cis2_combined_aal1", "nhs_login_combined"]:
token_data = self.create_authorization_code_token_data(
client_id=app["credentials"][0]["consumerKey"],
client_secret=app["credentials"][0]["consumerSecret"],
callback_url=app["callbackUrl"],
identity_url=nhsd_apim_proxy_url,
auth_pattern=auth_pattern,
)
elif auth_pattern == "cis2_seperate":
elif auth_pattern in ["cis2_seperate", "cis2_separate_aal2", "cis2_separate_aal1"]:
auth_pattern_aal_map = {
"cis2_separate_aal1": 1,
"cis2_separate_aal2": 2,
"cis2_seperate": 3,
}

cis2_subject_token_claims["authentication_assurance_level"] = auth_pattern_aal_map.get(auth_pattern)
token_data = self.create_token_exchange_token_data(
client_id=app["credentials"][0]["consumerKey"],
identity_url=nhsd_apim_proxy_url,
Expand Down Expand Up @@ -910,7 +955,19 @@ def test_flow_removes_external_scopes(
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
[],
"cis2_combined",
id="User-restricted-CIS2-combined: one product with invalid scope, one product with no scope",
id="User-restricted-CIS2-combined: one product with invalid scope (authed as aal3 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
[],
"cis2_combined_aal2",
id="User-restricted-CIS2-combined: one product with invalid scope (authed as aal2 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
[],
"cis2_combined_aal1",
id="User-restricted-CIS2-combined: one product with invalid scope (authed as aal1 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:app:level3:personal-demographics-service"],
Expand Down Expand Up @@ -1048,7 +1105,19 @@ def test_flow_removes_external_scopes(
["urn:nhsd:apim:user-nhs-id:aal2:personal-demographics-service"],
[],
"cis2_seperate",
id="User-restricted-CIS2-seperate: one product with invalid scope, one product with no scope",
id="User-restricted-CIS2-seperate: one product with invalid scope (authed as aal3 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
[],
"cis2_separate_aal2",
id="User-restricted-CIS2-separate: one product with invalid scope (authed as aal2 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"],
[],
"cis2_separate_aal1",
id="User-restricted-CIS2-separate: one product with invalid scope (authed as aal1 user), one product with no scope",
),
pytest.param(
["urn:nhsd:apim:app:level3:personal-demographics-service"],
Expand Down Expand Up @@ -1217,13 +1286,13 @@ def test_scope_combination_errors(
status_code = resp.status_code
error_content = resp.json()

elif auth_pattern == "cis2_combined" or auth_pattern == "nhs_login_combined":
elif auth_pattern in ["cis2_combined", "cis2_combined_aal2", "cis2_combined_aal1", "nhs_login_combined"]:
# Set up trace
session_name = str(uuid4())
header_filters = {"trace_id": session_name}
trace.post_debugsession(session=session_name, header_filters=header_filters)

token_data = self.hit_authorize_and_callback_endpoints(
self.hit_authorize_and_callback_endpoints(
client_id=app["credentials"][0]["consumerKey"],
callback_url=app["callbackUrl"],
identity_url=nhsd_apim_proxy_url,
Expand All @@ -1240,7 +1309,14 @@ def test_scope_combination_errors(

trace.delete_debugsession_by_name(session_name)

elif auth_pattern == "cis2_seperate":
elif auth_pattern in ["cis2_seperate", "cis2_separate_aal2", "cis2_separate_aal1"]:
auth_pattern_aal_map = {
"cis2_separate_aal1": 1,
"cis2_separate_aal2": 2,
"cis2_seperate": 3,
}

cis2_subject_token_claims["authentication_assurance_level"] = auth_pattern_aal_map.get(auth_pattern)
token_data = self.create_token_exchange_token_data(
client_id=app["credentials"][0]["consumerKey"],
identity_url=nhsd_apim_proxy_url,
Expand Down Expand Up @@ -1285,4 +1361,4 @@ def test_scope_combination_errors(
"error": "unauthorized_client",
"error_description": "you have tried to request authorization but your "
"application is not configured to use this authorization grant type",
}
}
7 changes: 7 additions & 0 deletions e2e/tests/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@
"ID_TOKEN_NHS_LOGIN_PRIVATE_KEY_ABSOLUTE_PATH"
]
JWT_PRIVATE_KEY_ABSOLUTE_PATH = environ["JWT_PRIVATE_KEY_ABSOLUTE_PATH"]


MOCK_CIS2_USERNAMES = {
"aal1": ["656005750110"],
"aal2": ["656005750109"],
"aal3": ["656005750104"],
}

0 comments on commit 05ca747

Please sign in to comment.