Ejemplo n.º 1
0
def setup_session(request):
    """This fixture is called at a function level.
    The default app created here should be modified by your tests.
    """
    product = asyncio.run(_product_with_full_access())
    print("\nCreating Default App..")
    # Create a new app
    app = ApigeeApiDeveloperApps()

    asyncio.run(
        app.create_new_app(callback_url="https://example.org/callback"))
    # Assign the new product to the app
    asyncio.run(app.add_api_product([product.name]))

    # Set default JWT Testing resource url
    asyncio.run(
        app.set_custom_attributes({
            'jwks-resource-url':
            'https://raw.githubusercontent.com/NHSDigital/'
            'identity-service-jwks/main/jwks/internal-dev/'
            '9baed6f4-1361-4a8e-8531-1f8426e3aba8.json'
        }))

    asyncio.run(product.update_environments([config.ENVIRONMENT]))
    oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    resp = asyncio.run(
        oauth.get_token_response(grant_type="authorization_code"))
    token = resp["body"]["access_token"]

    yield product, app, token

    # Teardown
    print("\nDestroying Default App..")
    asyncio.run(app.destroy_app())
    asyncio.run(product.destroy_product())
    async def test_no_role_provided(self, test_app):
        oauth = OauthHelper(
            client_id=test_app.client_id,
            client_secret=test_app.client_secret,
            redirect_uri=test_app.callback_url,
        )
        jwt = oauth.create_jwt(kid="test-1")
        token = await oauth.get_token_response(grant_type="client_credentials",
                                               _jwt=jwt)
        token = token["body"]["access_token"]
        # Given
        expected_status_code = 400
        expected_error = "invalid role"
        expected_error_description = "selected_roleid is missing in your token"

        # When
        response = requests.get(
            url=config.USER_ROLE_SHARED_FLOW,
            headers={"Authorization": f"Bearer {token}"},
        )
        # Then
        assert_that(expected_status_code).is_equal_to(response.status_code)
        assert_that(expected_error).is_equal_to(response.json()["error"])
        assert_that(expected_error_description).is_equal_to(
            response.json()["error_description"])
Ejemplo n.º 3
0
async def get_token_cis2_token_exchange(
    test_app_and_product, product_1_scopes, product_2_scopes
):
    """Call identity server to get an access token"""
    test_product, test_product2, test_app = test_app_and_product
    await test_product.update_scopes(product_1_scopes)
    await test_product2.update_scopes(product_2_scopes)

    oauth = OauthHelper(
        client_id=test_app.client_id,
        client_secret=test_app.client_secret,
        redirect_uri=test_app.callback_url,
    )

    claims = {
        "at_hash": "tf_-lqpq36lwO7WmSBIJ6Q",
        "sub": "787807429511",
        "auditTrackingId": "91f694e6-3749-42fd-90b0-c3134b0d98f6-1546391",
        "amr": ["N3_SMARTCARD"],
        "iss": "https://am.nhsint.auth-ptl.cis2.spineservices.nhs.uk:443/"
        "openam/oauth2/realms/root/realms/NHSIdentity/realms/Healthcare",
        "tokenName": "id_token",
        "aud": "969567331415.apps.national",
        "c_hash": "bc7zzGkClC3MEiFQ3YhPKg",
        "acr": "AAL3_ANY",
        "org.forgerock.openidconnect.ops": "-I45NjmMDdMa-aNF2sr9hC7qEGQ",
        "s_hash": "LPJNul-wow4m6Dsqxbning",
        "azp": "969567331415.apps.national",
        "auth_time": 1610559802,
        "realm": "/NHSIdentity/Healthcare",
        "exp": int(time()) + 6000,
        "tokenType": "JWTToken",
        "iat": int(time()) - 100,
    }

    with open(config.ID_TOKEN_PRIVATE_KEY_ABSOLUTE_PATH, "r") as f:
        contents = f.read()

    client_assertion_jwt = oauth.create_jwt(kid="test-1")
    id_token_jwt = oauth.create_id_token_jwt(
        kid="identity-service-tests-1", claims=claims, signing_key=contents
    )

    # When
    token_resp = await oauth.get_token_response(
        grant_type="token_exchange",
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
            "subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
            "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
            "subject_token": id_token_jwt,
            "client_assertion": client_assertion_jwt,
        },
    )

    return token_resp
Ejemplo n.º 4
0
async def get_token_nhs_login_token_exchange(
    test_app_and_product, product_1_scopes, product_2_scopes
):
    """Call nhs login to get an access token"""
    test_product, test_product2, test_app = test_app_and_product
    await test_product.update_scopes(product_1_scopes)
    await test_product2.update_scopes(product_2_scopes)

    oauth = OauthHelper(
        client_id=test_app.client_id,
        client_secret=test_app.client_secret,
        redirect_uri=test_app.callback_url,
    )

    claims = {
        "sub": "8dc9fc1d-c3cb-48e1-ba62-b1532539ab6d",
        "birthdate": "1939-09-26",
        "nhs_number": "9482807146",
        "iss": "https://internal-dev.api.service.nhs.uk",
        "nonce": "randomnonce",
        "vtm": "https://auth.aos.signin.nhs.uk/trustmark/auth.aos.signin.nhs.uk",
        "aud": "java_test_client",
        "id_status": "verified",
        "token_use": "id",
        "surname": "CARTHY",
        "auth_time": 1617272144,
        "vot": "P9.Cp.Cd",
        "identity_proofing_level": "P9",
        "exp": int(time()) + 6000,
        "iat": int(time()) - 100,
        "family_name": "CARTHY",
        "jti": "b6d6a28e-b0bb-44e3-974f-bb245c0b688a",
    }

    with open(config.ID_TOKEN_NHS_LOGIN_PRIVATE_KEY_ABSOLUTE_PATH, "r") as f:
        contents = f.read()

    client_assertion_jwt = oauth.create_jwt(kid="test-1")
    id_token_jwt = oauth.create_id_token_jwt(
        kid="nhs-login", algorithm="RS512", claims=claims, signing_key=contents
    )

    # When
    token_resp = await oauth.get_token_response(
        grant_type="token_exchange",
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
            "subject_token_type": "urn:ietf:params:oauth:token-type:id_token",
            "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
            "subject_token": id_token_jwt,
            "client_assertion": client_assertion_jwt,
        },
    )

    return token_resp
Ejemplo n.º 5
0
    async def _setup_session(request):
        product = await _product_with_full_access()
        app = ApigeeApiDeveloperApps()

        print("\nCreating Default App..")
        await app.create_new_app(
            callback_url="https://nhsd-apim-testing-internal-dev.herokuapp.com/callback"
        )
        await app.add_api_product([product.name])

        # Set default JWT Testing resource url
        await app.set_custom_attributes(
            {
                "jwks-resource-url": "https://raw.githubusercontent.com/NHSDigital/"
                "identity-service-jwks/main/jwks/internal-dev/"
                "9baed6f4-1361-4a8e-8531-1f8426e3aba8.json"
            }
        )

        oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)

        for item in request.node.items:
            setattr(item.cls, "oauth", oauth)

        return app, product
Ejemplo n.º 6
0
    async def _token(
        grant_type: str = "authorization_code",
        test_app: ApigeeApiDeveloperApps = None,
        **kwargs,
    ):
        if test_app:
            # Use provided test app
            oauth = OauthHelper(
                test_app.client_id, test_app.client_secret, test_app.callback_url
            )
            print(oauth.base_uri)
            resp = await oauth.get_token_response(grant_type=grant_type, **kwargs)
        else:
            # Use default test app
            resp = await request.cls.oauth.get_token_response(
                grant_type=grant_type, **kwargs
            )

        if resp["status_code"] != 200:
            message = "unable to get token"
            raise RuntimeError(
                f"\n{'*' * len(message)}\n"
                f"MESSAGE: {message}\n"
                f"URL: {resp.get('url')}\n"
                f"STATUS CODE: {resp.get('status_code')}\n"
                f"RESPONSE: {resp.get('body')}\n"
                f"HEADERS: {resp.get('headers')}\n"
                f"{'*' * len(message)}\n"
            )
        return resp["body"]
    async def test_user_invalid_role_in_header(self, test_app):
        oauth = OauthHelper(
            client_id=test_app.client_id,
            client_secret=test_app.client_secret,
            redirect_uri=test_app.callback_url,
        )
        token = await oauth.get_token_response(grant_type="authorization_code")
        token = token["body"]["access_token"]
        # Given
        expected_status_code = 400
        expected_error = "invalid role"
        expected_error_description = "nhsd-session-urid is invalid"

        # When
        response = requests.get(
            url=config.USER_ROLE_SHARED_FLOW,
            headers={
                "Authorization": f"Bearer {token}",
                "NHSD-Session-URID": "notAuserRole123",
            },
        )

        # Then
        assert_that(expected_status_code).is_equal_to(response.status_code)
        assert_that(expected_error).is_equal_to(response.json()["error"])
        assert_that(expected_error_description).is_equal_to(
            response.json()["error_description"])
    async def test_user_restricted_scope_combination(self, product_1_scopes,
                                                     product_2_scopes,
                                                     test_app_and_product,
                                                     helper):
        test_product, test_product2, test_app = test_app_and_product

        await test_product.update_scopes(product_1_scopes)
        await test_product2.update_scopes(product_2_scopes)

        callback_url = await test_app.get_callback_url()

        oauth = OauthHelper(test_app.client_id, test_app.client_secret,
                            callback_url)

        assert helper.check_endpoint(
            verb="POST",
            endpoint=f"{config.OAUTH_URL}/token",
            expected_status_code=200,
            expected_response=[
                "access_token",
                "expires_in",
                "refresh_count",
                "refresh_token",
                "refresh_token_expires_in",
                "token_type",
            ],
            data={
                "client_id": test_app.get_client_id(),
                "client_secret": test_app.get_client_secret(),
                "redirect_uri": callback_url,
                "grant_type": "authorization_code",
                "code": await oauth.get_authenticated_with_simulated_auth(),
            },
        )
Ejemplo n.º 9
0
async def test_app():
    """Programatically create and destroy test app for each test"""
    apigee_product = ApigeeApiProducts()
    await apigee_product.create_new_product()
    await apigee_product.update_proxies([config.SERVICE_NAME])

    apigee_app = ApigeeApiDeveloperApps()

    await apigee_product.update_ratelimits(
        quota=60000,
        quota_interval="1",
        quota_time_unit="minute",
        rate_limit="1000ps",
    )

    await apigee_app.setup_app(
        api_products=[apigee_product.name],
        custom_attributes={
            "jwks-resource-url":
            "https://internal-dev.api.service.nhs.uk/mock-nhsid-jwks/identity-service/nhs-cis2-jwks"
        })

    apigee_app.oauth = OauthHelper(apigee_app.client_id,
                                   apigee_app.client_secret,
                                   apigee_app.callback_url)

    api_service_name = get_env("SERVICE_NAME")

    await apigee_product.update_scopes(
        ["urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"])

    yield apigee_app

    await apigee_app.destroy_app()
Ejemplo n.º 10
0
def setup_session(request):
    """This fixture is automatically called once at the start of pytest execution.
    The default app created here should be modified by your tests.
    If your test requires specific app config then please create your own using
    the fixture test_app"""
    product = asyncio.run(_product_with_full_access())
    app = ApigeeApiDeveloperApps()

    print("\nCreating Default App..")
    asyncio.run(
        app.create_new_app(
            callback_url=
            "https://nhsd-apim-testing-internal-dev.herokuapp.com/callback"))
    asyncio.run(app.add_api_product([product.name]))

    # Set default JWT Testing resource url
    asyncio.run(
        app.set_custom_attributes({
            'jwks-resource-url':
            'https://raw.githubusercontent.com/NHSDigital/'
            'identity-service-jwks/main/jwks/internal-dev/'
            '9baed6f4-1361-4a8e-8531-1f8426e3aba8.json'
        }))

    oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    for item in request.node.items:
        setattr(item.cls, "oauth", oauth)

    yield

    # Teardown
    print("\nDestroying Default App..")
    asyncio.run(app.destroy_app())
    asyncio.run(product.destroy_product())
 async def get_token(self, test_app_and_product):
     """Call identity server to get an access token"""
     test_product, test_app = test_app_and_product
     oauth = OauthHelper(client_id=test_app.client_id,
                         client_secret=test_app.client_secret,
                         redirect_uri=test_app.callback_url)
     token_resp = await oauth.get_token_response(
         grant_type="authorization_code")
     assert token_resp["status_code"] == 200
     return token_resp['body']
def test_product_and_app():
    """Setup & Teardown an product and app for this api"""
    product = ApigeeApiProducts()
    app = ApigeeApiDeveloperApps()
    loop = asyncio.new_event_loop()
    loop.run_until_complete(product.create_new_product())
    loop.run_until_complete(app.setup_app())
    app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    yield product, app
    loop.run_until_complete(app.destroy_app())
    loop.run_until_complete(product.destroy_product())
Ejemplo n.º 13
0
def base_test_app():
    """Setup & Teardown an app-restricted app for this api"""
    app = ApigeeApiDeveloperApps()
    loop = asyncio.new_event_loop()
    loop.run_until_complete(
        app.setup_app(
            api_products=[get_env("APIGEE_PRODUCT")],
            custom_attributes=_BASE_CUSTOM_ATTRIBUTES,
        ))
    app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    yield app
    loop.run_until_complete(app.destroy_app())
Ejemplo n.º 14
0
    async def test_cis2_user_restricted_scope_combination(
        self,
        product_1_scopes,
        product_2_scopes,
        expected_filtered_scopes,
        test_app_and_product,
        helper,
    ):
        test_product, test_product2, test_app = test_app_and_product

        await test_product.update_scopes(product_1_scopes)
        await test_product2.update_scopes(product_2_scopes)
        apigee_trace = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)

        callback_url = await test_app.get_callback_url()
        oauth = OauthHelper(test_app.client_id, test_app.client_secret,
                            callback_url)

        apigee_trace.add_trace_filter(header_name="Auto-Test-Header",
                                      header_value="flow-callback")
        await apigee_trace.start_trace()

        assert helper.check_endpoint(
            verb="POST",
            endpoint=f"{config.OAUTH_URL}/token",
            expected_status_code=200,
            expected_response=[
                "access_token",
                "expires_in",
                "refresh_count",
                "refresh_token",
                "refresh_token_expires_in",
                "sid",
                "token_type",
            ],
            data={
                "client_id": test_app.get_client_id(),
                "client_secret": test_app.get_client_secret(),
                "redirect_uri": callback_url,
                "grant_type": "authorization_code",
                "code": await oauth.get_authenticated_with_simulated_auth(),
            },
        )

        user_restricted_scopes = await apigee_trace.get_apigee_variable_from_trace(
            name="apigee.user_restricted_scopes")
        assert (
            user_restricted_scopes is not None
        ), "variable apigee.user_restricted_scopes not found in the trace"
        user_restricted_scopes = user_restricted_scopes.split(" ")
        assert expected_filtered_scopes.sort() == user_restricted_scopes.sort()
def test_app():
    """Setup & Teardown an app-restricted app for this api"""
    app = ApigeeApiDeveloperApps()
    loop = asyncio.new_event_loop()
    loop.run_until_complete(
        app.setup_app(
            api_products=[get_env("APIGEE_PRODUCT")],
            custom_attributes={
                "jwks-resource-url": "https://raw.githubusercontent.com/NHSDigital/identity-service-jwks/main/jwks/internal-dev/9baed6f4-1361-4a8e-8531-1f8426e3aba8.json"  # noqa
            },
        )
    )
    app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    yield app
    loop.run_until_complete(app.destroy_app())
    async def test_default_role(self, test_app):
        oauth = OauthHelper(
            client_id=test_app.client_id,
            client_secret=test_app.client_secret,
            redirect_uri=test_app.callback_url,
        )
        token = await oauth.get_token_response(grant_type="authorization_code")
        token = token["body"]["access_token"]
        # Given
        expected_status_code = 200
        expected_response = {"message": "It works!"}

        # When
        response = requests.get(
            url=config.USER_ROLE_SHARED_FLOW,
            headers={"Authorization": f"Bearer {token}"},
        )
        # Then
        assert_that(expected_status_code).is_equal_to(response.status_code)
        assert_that(expected_response).is_equal_to(response.json())
Ejemplo n.º 17
0
def test_product_and_app():
    """Setup & Teardown an product and app for this api"""
    product = ApigeeApiProducts()
    app = ApigeeApiDeveloperApps()
    loop = asyncio.new_event_loop()
    loop.run_until_complete(product.create_new_product())
    loop.run_until_complete(
        product.update_scopes([
            "urn:nhsd:apim:app:level3:immunisation-history",
            "urn:nhsd:apim:user-nhs-login:P9:immunisation-history",
            "urn:nhsd:apim:user-nhs-login:P5:immunisation-history"
        ]))
    loop.run_until_complete(
        app.setup_app(
            api_products=[product.name],
            custom_attributes=_BASE_CUSTOM_ATTRIBUTES,
        ))
    app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    yield product, app
    loop.run_until_complete(app.destroy_app())
    loop.run_until_complete(product.destroy_product())
Ejemplo n.º 18
0
    async def test_authorization_code_flow_remove_external_scopes(
            self, test_app_and_product, helper, external_scope):
        product_scope = [
            "urn:nhsd:apim:user-nhs-id:aal3:personal-demographics-service"
        ]
        test_product, test_product2, test_app = test_app_and_product

        await test_product.update_scopes(product_scope)
        await test_product2.update_scopes(product_scope)

        callback_url = await test_app.get_callback_url()

        oauth = OauthHelper(test_app.client_id, test_app.client_secret,
                            callback_url)

        assert helper.check_endpoint(
            verb="POST",
            endpoint=f"{config.OAUTH_URL}/token",
            expected_status_code=200,
            expected_response=[
                "access_token",
                "expires_in",
                "refresh_count",
                "refresh_token",
                "refresh_token_expires_in",
                "sid",
                "token_type",
            ],
            data={
                "scope": external_scope,
                "client_id": test_app.get_client_id(),
                "client_secret": test_app.get_client_secret(),
                "redirect_uri": callback_url,
                "grant_type": "authorization_code",
                "code": await oauth.get_authenticated_with_simulated_auth(),
            },
        )
Ejemplo n.º 19
0
def test_product_and_app(request):
    """Setup & Teardown an product and app for this api"""
    request_params = request.param
    product = ApigeeApiProducts()
    app = ApigeeApiDeveloperApps()
    loop = asyncio.new_event_loop()
    loop.run_until_complete(product.create_new_product())
    loop.run_until_complete(product.update_scopes(
        request_params['scopes']
    ))
    loop.run_until_complete(
        app.setup_app(
            api_products=[product.name],
            custom_attributes= {
                "jwks-resource-url": "https://raw.githubusercontent.com/NHSDigital/identity-service-jwks/main/jwks/internal-dev/9baed6f4-1361-4a8e-8531-1f8426e3aba8.json",
                "nhs-login-allowed-proofing-level": request_params.get('requested_proofing_level')
            },
        )
    )
    app.oauth = OauthHelper(app.client_id, app.client_secret, app.callback_url)
    app.request_params = request_params
    yield product, app
    loop.run_until_complete(app.destroy_app())
    loop.run_until_complete(product.destroy_product())
def _oauth(_test_app):
    """Return an instance of OauthHelper to the test"""
    return OauthHelper(client_id=_test_app.client_id,
                       client_secret=_test_app.client_secret,
                       redirect_uri=_test_app.callback_url)