diff --git a/maskinporten_api/maskinporten_client.py b/maskinporten_api/maskinporten_client.py index b6374aa..af45027 100644 --- a/maskinporten_api/maskinporten_client.py +++ b/maskinporten_api/maskinporten_client.py @@ -155,17 +155,19 @@ def create_idporten_client( "application_type": "web", "authorization_lifetime": 0, "client_name": self._make_client_name(team_name, provider, integration), - "client_uri": client_uri, + "client_uri": str(client_uri), "description": self._make_client_description( team_name, provider, integration ), "code_challenge_method": "S256", "frontchannel_logout_session_required": True, - "frontchannel_logout_uri": frontchannel_logout_uri, + "frontchannel_logout_uri": str(frontchannel_logout_uri), "grant_types": ["authorization_code", "refresh_token"], "integration_type": "idporten", - "post_logout_redirect_uris": post_logout_redirect_uris, - "redirect_uris": redirect_uris, + "post_logout_redirect_uris": [ + str(u) for u in post_logout_redirect_uris + ], + "redirect_uris": [str(u) for u in redirect_uris], "refresh_token_lifetime": 0, "refresh_token_usage": "ONETIME", "scopes": ["openid", "profile"], diff --git a/test/resources/conftest.py b/test/resources/conftest.py index 4d498f6..a9ad8f8 100644 --- a/test/resources/conftest.py +++ b/test/resources/conftest.py @@ -58,7 +58,7 @@ def get_mock_user(principal_id): return None -def generate_mock_client_response( +def maskinporten_client_response( client_id, client_name, scopes=["folkeregister:deling/offentligmedhjemmel"], @@ -84,6 +84,35 @@ def generate_mock_client_response( } +def idporten_client_response(client_id, client_name): + return { + "client_name": client_name, + "client_uri": "http://localhost:8000", + "description": "Test client", + "scopes": ["openid", "profile"], + "redirect_uris": ["http://localhost:8000/auth/callback"], + "post_logout_redirect_uris": ["http://localhost:8000/"], + "authorization_lifetime": 0, + "access_token_lifetime": 0, + "refresh_token_lifetime": 0, + "refresh_token_usage": "ONETIME", + "frontchannel_logout_uri": "http://localhost:8000/auth/logout", + "frontchannel_logout_session_required": True, + "token_endpoint_auth_method": "private_key_jwt", + "grant_types": ["authorization_code", "refresh_token"], + "integration_type": "idporten", + "application_type": "web", + "sso_disabled": False, + "code_challenge_method": "S256", + "last_updated": "2024-01-01T20:00:00.000Z", + "created": "2024-01-01T20:00:00.000Z", + "client_id": client_id, + "client_orgno": "123456789", + "active": True, + "jwks_uri": f"/clients/{client_id}/jwks", + } + + @pytest.fixture def maskinporten_create_client_body(): return { @@ -113,15 +142,18 @@ def idporten_create_client_body(): @pytest.fixture def maskinporten_create_client_response(): - return generate_mock_client_response( + return maskinporten_client_response( client_id="d1427568-1eba-1bf2-59ed-1c4af065f30e", client_name="my-team-freg-testing", ) @pytest.fixture -def idporten_create_client_response(maskinporten_create_client_response): - return maskinporten_create_client_response +def idporten_create_client_response(): + return idporten_client_response( + client_id="1a7a504d-bb4c-239d-1469-61e220c3bcb6", + client_name="my-team-idporten-testing", + ) @pytest.fixture @@ -134,7 +166,7 @@ def maskinporten_get_client_response(maskinporten_create_client_response): def maskinporten_get_clients_response(maskinporten_get_client_response): return [ maskinporten_get_client_response, - generate_mock_client_response( + maskinporten_client_response( client_id="a70c6d97-51c2-4a08-83ce-50f44ebf8921", client_name="another-client", ), diff --git a/test/resources/test_maskinporten.py b/test/resources/test_maskinporten.py index 85d1401..b9df858 100644 --- a/test/resources/test_maskinporten.py +++ b/test/resources/test_maskinporten.py @@ -1,5 +1,5 @@ import os -from unittest.mock import Mock, patch +from unittest.mock import patch import pytest import requests_mock @@ -101,24 +101,73 @@ def test_create_client_idporten( idporten_create_client_response, user_team_response, mock_authorizer, + mock_aws, mock_client, + mock_dynamodb, + mocker, ): with requests_mock.Mocker(real_http=True) as rm: + mock_user = get_mock_user("janedoe") mock_access_token_generation_requests(rm) - rm.get(f"{OKDATA_PERMISSION_API_URL}/teams/{team_id}", json=user_team_response) - with patch("resources.maskinporten.MaskinportenClient") as MaskinportenClient: - mocked_maskinporten_client = Mock() - MaskinportenClient.return_value = mocked_maskinporten_client - mocked_maskinporten_client.create_idporten_client.return_value.json.return_value = ( - idporten_create_client_response - ) - mock_client.post( - "/clients", - json=idporten_create_client_body, - headers={"Authorization": get_mock_user("janedoe").bearer_token}, - ) - mocked_maskinporten_client.create_idporten_client.assert_called_once() + rm.post(CLIENTS_ENDPOINT, json=idporten_create_client_response) + + teams_api_matcher = rm.get( + f"{OKDATA_PERMISSION_API_URL}/teams/{team_id}", + json=user_team_response, + ) + permissions_api_matcher = rm.post( + f"{OKDATA_PERMISSION_API_URL}/permissions", + ) + audit_notify_matcher = rm.post(SLACK_WEBHOOK_URL) + + created_client = mock_client.post( + "/clients", + json=idporten_create_client_body, + headers={"Authorization": mock_user.bearer_token}, + ).json() + + client = { + "client_id": "1a7a504d-bb4c-239d-1469-61e220c3bcb6", + "client_name": "my-team-idporten-testing", + "description": "Test client", + "scopes": ["openid", "profile"], + "created": "2024-01-01T20:00:00+00:00", + "last_updated": "2024-01-01T20:00:00+00:00", + "active": True, + } + assert created_client == client + + teams_request = teams_api_matcher.last_request + assert teams_request.headers["Authorization"] == f"Bearer {mock_user.access_token}" + + permissions_request = permissions_api_matcher.last_request + assert ( + permissions_request.headers["Authorization"] == f"Bearer {valid_client_token}" + ) + resource_name = client_resource_name( + idporten_create_client_body["env"], client["client_id"] + ) + assert permissions_request.json() == { + "owner": { + "user_id": user_team_response["name"], + "user_type": "team", + }, + "resource_name": resource_name, + } + + table = mock_dynamodb.Table("maskinporten-audit-trail") + audit_log_entry = table.query(KeyConditionExpression=Key("Id").eq(resource_name))[ + "Items" + ][0] + assert audit_log_entry["Action"] == "create" + + assert audit_notify_matcher.last_request.json() == _slack_message_payload( + "Client created", + client["client_name"], + idporten_create_client_body["env"], + client["scopes"], + ) def test_create_client_rollback(