11import pytest
22import requests
3+ from time import time
34from assertpy import assert_that
5+ from .configuration import config
46from api_test_utils .oauth_helper import OauthHelper
57from api_test_utils .apigee_api_apps import ApigeeApiDeveloperApps
68from api_test_utils .apigee_api_products import ApigeeApiProducts
79
810
911class TestEndpoints :
10-
1112 @pytest .fixture ()
1213 def app (self ):
1314 """
@@ -40,11 +41,21 @@ async def test_app_and_product(self, app, product):
4041
4142 await app .create_new_app ()
4243
43- await product .update_scopes ([
44- "urn:nhsd:apim:app:level3:shared-flow-testing" ,
45- "urn:nhsd:apim:user-nhs-id:aal3:shared-flow-testing"
46- ])
44+ await product .update_scopes (
45+ [
46+ "urn:nhsd:apim:app:level3:shared-flow-testing" ,
47+ "urn:nhsd:apim:user-nhs-id:aal3:shared-flow-testing" ,
48+ "urn:nhsd:apim:user-nhs-login:P9:shared-flow-testing" ,
49+ ]
50+ )
4751 await app .add_api_product ([product .name ])
52+ await app .set_custom_attributes (
53+ {
54+ "jwks-resource-url" : "https://raw.githubusercontent.com/NHSDigital/"
55+ "identity-service-jwks/main/jwks/internal-dev/"
56+ "9baed6f4-1361-4a8e-8531-1f8426e3aba8.json"
57+ }
58+ )
4859
4960 yield product , app
5061
@@ -58,22 +69,130 @@ async def get_token(self, test_app_and_product):
5869 oauth = OauthHelper (
5970 client_id = test_app .client_id ,
6071 client_secret = test_app .client_secret ,
61- redirect_uri = test_app .callback_url
62- )
72+ redirect_uri = test_app .callback_url ,
73+ )
6374 token_resp = await oauth .get_token_response (grant_type = "authorization_code" )
6475 assert token_resp ["status_code" ] == 200
65- return token_resp ['body' ]
76+ return token_resp ["body" ]
77+
78+ @pytest .fixture ()
79+ async def get_token_client_credentials (self , test_app_and_product ):
80+ """Call identity server to get an access token"""
81+ test_product , test_app = test_app_and_product
82+ oauth = OauthHelper (
83+ client_id = test_app .client_id ,
84+ client_secret = test_app .client_secret ,
85+ redirect_uri = test_app .callback_url ,
86+ )
87+ jwt = oauth .create_jwt (kid = "test-1" )
88+ token_resp = await oauth .get_token_response (
89+ grant_type = "client_credentials" , _jwt = jwt
90+ )
91+ assert token_resp ["status_code" ] == 200
92+ return token_resp ["body" ]
93+
94+ @pytest .fixture ()
95+ async def get_token_nhs_login_token_exchange (self , test_app_and_product ):
96+ """Call identity server to get an access token"""
97+ test_product , test_app = test_app_and_product
98+ oauth = OauthHelper (
99+ client_id = test_app .client_id ,
100+ client_secret = test_app .client_secret ,
101+ redirect_uri = test_app .callback_url ,
102+ )
103+
104+ id_token_claims = {
105+ "aud" : "tf_-APIM-1" ,
106+ "id_status" : "verified" ,
107+ "token_use" : "id" ,
108+ "auth_time" : 1616600683 ,
109+ "iss" : "https://internal-dev.api.service.nhs.uk" ,
110+ "vot" : "P9.Cp.Cd" ,
111+ "exp" : int (time ()) + 600 ,
112+ "iat" : int (time ()) - 10 ,
113+ "vtm" : "https://auth.sandpit.signin.nhs.uk/trustmark/auth.sandpit.signin.nhs.uk" ,
114+ "jti" : "b68ddb28-e440-443d-8725-dfe0da330118" ,
115+ "identity_proofing_level" : "P9" ,
116+ }
117+ id_token_headers = {
118+ "sub" : "49f470a1-cc52-49b7-beba-0f9cec937c46" ,
119+ "aud" : "APIM-1" ,
120+ "kid" : "nhs-login" ,
121+ "iss" : "https://internal-dev.api.service.nhs.uk" ,
122+ "typ" : "JWT" ,
123+ "exp" : 1616604574 ,
124+ "iat" : 1616600974 ,
125+ "alg" : "RS512" ,
126+ "jti" : "b68ddb28-e440-443d-8725-dfe0da330118" ,
127+ }
128+ with open (config .ID_TOKEN_NHS_LOGIN_PRIVATE_KEY_ABSOLUTE_PATH , "r" ) as f :
129+ contents = f .read ()
130+
131+ client_assertion_jwt = oauth .create_jwt (kid = "test-1" )
132+ id_token_jwt = oauth .create_id_token_jwt (
133+ algorithm = "RS512" ,
134+ claims = id_token_claims ,
135+ headers = id_token_headers ,
136+ signing_key = contents ,
137+ )
138+
139+ # When
140+ token_resp = await oauth .get_token_response (
141+ grant_type = "token_exchange" ,
142+ data = {
143+ "grant_type" : "urn:ietf:params:oauth:grant-type:token-exchange" ,
144+ "subject_token_type" : "urn:ietf:params:oauth:token-type:id_token" ,
145+ "client_assertion_type" : "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" ,
146+ "subject_token" : id_token_jwt ,
147+ "client_assertion" : client_assertion_jwt ,
148+ },
149+ )
150+ assert token_resp ["status_code" ] == 200
151+ return token_resp ["body" ]
152+
153+ @pytest .mark .asyncio
154+ async def test_happy_path (self , get_token ):
155+ # Given
156+ token = get_token ["access_token" ]
157+ expected_status_code = 200
158+
159+ # When
160+ response = requests .get (
161+ url = "https://internal-dev.api.service.nhs.uk/shared-flow-testing/user-role-service" ,
162+ headers = {
163+ "Authorization" : f"Bearer { token } " ,
164+ "NHSD-Session-URID" : "555254242102" ,
165+ },
166+ )
66167
67- def test_user_invalid_role_in_header (self , get_token ):
168+ # Then
169+ assert_that (expected_status_code ).is_equal_to (response .status_code )
170+
171+ @pytest .mark .asyncio
172+ async def test_default_role (self , get_token ):
173+ # Given
174+ token = get_token ["access_token" ]
175+ expected_status_code = 200
176+
177+ # When
178+ response = requests .get (
179+ url = "https://internal-dev.api.service.nhs.uk/shared-flow-testing/user-role-service" ,
180+ headers = {"Authorization" : f"Bearer { token } " },
181+ )
182+ # Then
183+ assert_that (expected_status_code ).is_equal_to (response .status_code )
184+
185+ @pytest .mark .asyncio
186+ async def test_user_invalid_role_in_header (self , get_token ):
68187 # Given
69- token = get_token [' access_token' ]
188+ token = get_token [" access_token" ]
70189 expected_status_code = 400
71190 expected_error = "invalid role"
72191 expected_error_description = "nhsd-session-urid is invalid"
73192
74193 # When
75194 response = requests .get (
76- url = ' https://internal-dev.api.service.nhs.uk/shared-flow-testing-pr-6 /user-role-service' ,
195+ url = " https://internal-dev.api.service.nhs.uk/shared-flow-testing/user-role-service" ,
77196 headers = {
78197 "Authorization" : f"Bearer { token } " ,
79198 "NHSD-Session-URID" : "notAuserRole123" ,
@@ -86,3 +205,45 @@ def test_user_invalid_role_in_header(self, get_token):
86205 assert_that (expected_error_description ).is_equal_to (
87206 response .json ()["error_description" ]
88207 )
208+
209+ @pytest .mark .asyncio
210+ async def test_no_role_provided (self , get_token_client_credentials ):
211+ token = get_token_client_credentials ["access_token" ]
212+ # Given
213+ expected_status_code = 400
214+ expected_error = "invalid role"
215+ expected_error_description = "selected_roleid is missing in your token"
216+
217+ # When
218+ response = requests .get (
219+ url = "https://internal-dev.api.service.nhs.uk/shared-flow-testing/user-role-service" ,
220+ headers = {"Authorization" : f"Bearer { token } " },
221+ )
222+ # Then
223+ assert_that (expected_status_code ).is_equal_to (response .status_code )
224+ assert_that (expected_error ).is_equal_to (response .json ()["error" ])
225+ assert_that (expected_error_description ).is_equal_to (
226+ response .json ()["error_description" ]
227+ )
228+
229+ @pytest .mark .asyncio
230+ async def test_nhs_login_exchanged_token_no_role_provided (
231+ self , get_token_nhs_login_token_exchange
232+ ):
233+ token = get_token_nhs_login_token_exchange ["access_token" ]
234+ # Given
235+ expected_status_code = 400
236+ expected_error = "invalid role"
237+ expected_error_description = "selected_roleid is missing in your token"
238+
239+ # When
240+ response = requests .get (
241+ url = "https://internal-dev.api.service.nhs.uk/shared-flow-testing/user-role-service" ,
242+ headers = {"Authorization" : f"Bearer { token } " },
243+ )
244+ # Then
245+ assert_that (expected_status_code ).is_equal_to (response .status_code )
246+ assert_that (expected_error ).is_equal_to (response .json ()["error" ])
247+ assert_that (expected_error_description ).is_equal_to (
248+ response .json ()["error_description" ]
249+ )
0 commit comments