def test_invalidate_signature_invalid_params( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, # hsa_username missing "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) # Invalidate the signature invalidate_url = reverse("invalidate_hauki_auth_signature") response = api_client.post(invalidate_url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 403
def test_get_auth_required_header_invalid_valid_until( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) url = reverse("auth_required_test-list") data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": "2020-01-01T10:10:10.000Z", "hsa_valid_until": "2000-01-01T10:20:10.000Z", } source_string = join_params(data) signature = calculate_signature(signed_auth_key.signing_key, source_string) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 403 assert str(response.data["detail"]) == "Invalid hsa_valid_until"
def test_authenticate_existing_user_existing_same_data_source( api_client, data_source, signed_auth_key_factory, user_factory, user_origin_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) user = user_factory() user_origin_factory(user=user, data_source=data_source) now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": user.username, "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } source_string = join_params(data) signature = calculate_signature(signed_auth_key.signing_key, source_string) params = {**data, "hsa_signature": signature} # Create a fake DRF request request_factory = APIRequestFactory() http_request = request_factory.get("/", params) request = APIView().initialize_request(http_request) auth = HaukiSignedAuthentication() authenticated_user = auth.authenticate(request)[0] assert authenticated_user.id == user.id assert authenticated_user.username == user.username
def test_join_user_to_organization_invalid_org( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", "hsa_organization": "test:2345", } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user" user = User.objects.get(username="******") assert user.organization_memberships.count() == 0
def test_get_auth_required_header_authenticated( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } source_string = join_params(data) signature = calculate_signature(signed_auth_key.signing_key, source_string) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user"
def test_get_auth_required_header_authenticated(settings, api_client): settings.HAUKI_SIGNED_AUTH_PSK = "testing" url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "username": "******", "created_at": now.isoformat() + "Z", "valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } source_string = join_params(data) signature = calculate_signature(source_string) authz_string = "haukisigned " + urllib.parse.urlencode({ **data, "signature": signature }) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user"
def test_join_user_to_organization_invalid_org(settings, api_client, data_source_factory, organization_factory): settings.HAUKI_SIGNED_AUTH_PSK = "testing" url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "username": "******", "created_at": now.isoformat() + "Z", "valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", "organization": "test:2345", } signature = calculate_signature(join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode({ **data, "signature": signature }) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user" user = User.objects.get(username="******") assert user.organization_memberships.count() == 0
def test_invalidate_signature_success_header_params( api_client, data_source, signed_auth_key_factory ): url = reverse("auth_required_test-list") signed_auth_key = signed_auth_key_factory(data_source=data_source) now = datetime.datetime.utcnow() valid_until = now + datetime.timedelta(minutes=10) data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": valid_until.isoformat() + "Z", } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) # Check that auth works response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user" # Invalidate the signature invalidate_url = reverse("invalidate_hauki_auth_signature") response = api_client.post(invalidate_url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data == {"success": True} signed_auth_entry = SignedAuthEntry.objects.get(signature=signature) assert signed_auth_entry.created_at == now.replace(tzinfo=UTC) assert signed_auth_entry.valid_until == valid_until.replace(tzinfo=UTC) # Verify that the auth no longer works response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 403
def test_join_user_to_organization_existing_user_and_organisation( api_client, user_factory, user_origin_factory, data_source_factory, signed_auth_key_factory, organization_factory, ): data_source = data_source_factory(id="test") user = user_factory(username="******") user_origin_factory(user=user, data_source=data_source) signed_auth_key = signed_auth_key_factory(data_source=data_source) org = organization_factory(data_source=data_source, origin_id=1234) user.organization_memberships.add(org) url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": user.username, "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", "hsa_organization": org.id, } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user" assert User.objects.count() == 1 assert user.organization_memberships.count() == 1
def test_signed_auth_entry_not_invalidated( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() valid_until = now + datetime.timedelta(minutes=10) data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": valid_until.isoformat() + "Z", } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "haukisigned " + urllib.parse.urlencode( {**data, "hsa_signature": signature} ) # Check that auth works response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user" # Add a non invalidated entry to the database SignedAuthEntry.objects.create( signature=signature, created_at=now.replace(tzinfo=UTC), valid_until=valid_until.replace(tzinfo=UTC), ) # Check that auth still works response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 200 assert response.data["username"] == "test_user"
def test_authenticate_existing_user_existing_different_data_source( api_client, data_source_factory, signed_auth_key_factory, user_factory, user_origin_factory, ): data_source1 = data_source_factory() data_source2 = data_source_factory() signed_auth_key = signed_auth_key_factory(data_source=data_source1) user = user_factory() user_origin_factory(user=user, data_source=data_source2) now = datetime.datetime.utcnow() data = { "hsa_source": data_source1.id, "hsa_username": user.username, "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } source_string = join_params(data) signature = calculate_signature(signed_auth_key.signing_key, source_string) params = {**data, "hsa_signature": signature} # Create a fake DRF request request_factory = APIRequestFactory() http_request = request_factory.get("/", params) request = APIView().initialize_request(http_request) auth = HaukiSignedAuthentication() with pytest.raises(AuthenticationFailed) as e: auth.authenticate(request)[0] assert e.value.detail == "User not from the same data source"
def _make_hsa_params( user=None, username=None, data_source=None, organization=None, resource=None, has_organization_rights=False, signed_auth_key=None, ): if not signed_auth_key: signed_auth_key = SignedAuthKeyFactory(data_source=data_source) now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": user.username if user else username, "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", "hsa_has_organization_rights": str(has_organization_rights), } if organization: data["hsa_organization"] = str(organization.id) if resource: data["hsa_resource"] = (str(resource.id) if isinstance( resource, Resource) else resource) source_string = join_params(data) signature = calculate_signature(signed_auth_key.signing_key, source_string) return {**data, "hsa_signature": signature}
def test_get_auth_required_header_invalid_valid_until(settings, api_client): settings.HAUKI_SIGNED_AUTH_PSK = "testing" url = reverse("auth_required_test-list") data = { "username": "******", "created_at": "2020-01-01T10:10:10.000Z", "valid_until": "2000-01-01T10:20:10.000Z", } source_string = join_params(data) signature = calculate_signature(source_string) authz_string = "haukisigned " + urllib.parse.urlencode({ **data, "signature": signature }) response = api_client.get(url, HTTP_AUTHORIZATION=authz_string) assert response.status_code == 403 assert str(response.data["detail"]) == "Invalid valid_until"
def test_invalidate_signature_success_query_params( api_client, data_source, signed_auth_key_factory ): signed_auth_key = signed_auth_key_factory(data_source=data_source) url = reverse("auth_required_test-list") now = datetime.datetime.utcnow() data = { "hsa_source": data_source.id, "hsa_username": "******", "hsa_created_at": now.isoformat() + "Z", "hsa_valid_until": (now + datetime.timedelta(minutes=10)).isoformat() + "Z", } signature = calculate_signature(signed_auth_key.signing_key, join_params(data)) authz_string = "?" + urllib.parse.urlencode({**data, "hsa_signature": signature}) # Check that auth works response = api_client.get(f"{url}{authz_string}") assert response.status_code == 200 assert response.data["username"] == "test_user" # Invalidate the signature invalidate_url = reverse("invalidate_hauki_auth_signature") response = api_client.post(f"{invalidate_url}{authz_string}") assert response.status_code == 200 assert response.data == {"success": True} # Verify that the auth no longer works response = api_client.get(f"{url}{authz_string}") assert response.status_code == 403