Skip to content
Snippets Groups Projects
test_authentication.py 5.81 KiB
Newer Older
  • Learn to ignore specific revisions
  • import pytest
    
    from funkwhale_api.federation import authentication, exceptions, keys
    
    def test_authenticate(factories, mocker, api_request):
    
        private, public = keys.get_key_pair()
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        actor_url = "https://test.federation/actor"
    
        mocker.patch(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            "funkwhale_api.federation.actors.get_actor_data",
    
            return_value={
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "id": actor_url,
                "type": "Person",
                "outbox": "https://test.com",
                "inbox": "https://test.com",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "followers": "https://test.com",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "preferredUsername": "test",
                "publicKey": {
                    "publicKeyPem": public.decode("utf-8"),
                    "owner": actor_url,
                    "id": actor_url + "#main-key",
                },
            },
        )
        signed_request = factories["federation.SignedRequest"](
            auth__key=private, auth__key_id=actor_url + "#main-key", auth__headers=["date"]
    
        )
        prepared = signed_request.prepare()
        django_request = api_request.get(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            "/",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "HTTP_DATE": prepared.headers["date"],
                "HTTP_SIGNATURE": prepared.headers["signature"],
    
            }
        )
        authenticator = authentication.SignatureAuthentication()
        user, _ = authenticator.authenticate(django_request)
        actor = django_request.actor
    
        assert user.is_anonymous is True
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        assert actor.public_key == public.decode("utf-8")
    
        assert actor.fid == actor_url
    
    
    
    def test_authenticate_skips_blocked_domain(factories, api_request):
        policy = factories["moderation.InstancePolicy"](block_all=True, for_domain=True)
        private, public = keys.get_key_pair()
        actor_url = "https://{}/actor".format(policy.target_domain.name)
    
        signed_request = factories["federation.SignedRequest"](
            auth__key=private, auth__key_id=actor_url + "#main-key", auth__headers=["date"]
        )
        prepared = signed_request.prepare()
        django_request = api_request.get(
            "/",
            **{
                "HTTP_DATE": prepared.headers["date"],
                "HTTP_SIGNATURE": prepared.headers["signature"],
            }
        )
        authenticator = authentication.SignatureAuthentication()
    
        with pytest.raises(exceptions.BlockedActorOrDomain):
            authenticator.authenticate(django_request)
    
    
    def test_authenticate_skips_blocked_actor(factories, api_request):
        policy = factories["moderation.InstancePolicy"](block_all=True, for_actor=True)
        private, public = keys.get_key_pair()
        actor_url = policy.target_actor.fid
    
        signed_request = factories["federation.SignedRequest"](
            auth__key=private, auth__key_id=actor_url + "#main-key", auth__headers=["date"]
        )
        prepared = signed_request.prepare()
        django_request = api_request.get(
            "/",
            **{
                "HTTP_DATE": prepared.headers["date"],
                "HTTP_SIGNATURE": prepared.headers["signature"],
            }
        )
        authenticator = authentication.SignatureAuthentication()
    
        with pytest.raises(exceptions.BlockedActorOrDomain):
            authenticator.authenticate(django_request)
    
    
    def test_authenticate_ignore_inactive_policy(factories, api_request, mocker):
        policy = factories["moderation.InstancePolicy"](
            block_all=True, for_domain=True, is_active=False
        )
        private, public = keys.get_key_pair()
        actor_url = "https://{}/actor".format(policy.target_domain.name)
    
        signed_request = factories["federation.SignedRequest"](
            auth__key=private, auth__key_id=actor_url + "#main-key", auth__headers=["date"]
        )
        mocker.patch(
            "funkwhale_api.federation.actors.get_actor_data",
            return_value={
                "id": actor_url,
                "type": "Person",
                "outbox": "https://test.com",
                "inbox": "https://test.com",
                "followers": "https://test.com",
                "preferredUsername": "test",
                "publicKey": {
                    "publicKeyPem": public.decode("utf-8"),
                    "owner": actor_url,
                    "id": actor_url + "#main-key",
                },
            },
        )
        prepared = signed_request.prepare()
        django_request = api_request.get(
            "/",
            **{
                "HTTP_DATE": prepared.headers["date"],
                "HTTP_SIGNATURE": prepared.headers["signature"],
            }
        )
        authenticator = authentication.SignatureAuthentication()
        authenticator.authenticate(django_request)
        actor = django_request.actor
    
        assert actor.public_key == public.decode("utf-8")
        assert actor.fid == actor_url
    
    
    
    def test_autenthicate_supports_blind_key_rotation(factories, mocker, api_request):
        actor = factories["federation.Actor"]()
        actor_url = actor.fid
        # request is signed with a pair of new keys
        new_private, new_public = keys.get_key_pair()
        mocker.patch(
            "funkwhale_api.federation.actors.get_actor_data",
            return_value={
                "id": actor_url,
                "type": "Person",
                "outbox": "https://test.com",
                "inbox": "https://test.com",
                "followers": "https://test.com",
                "preferredUsername": "test",
                "publicKey": {
                    "publicKeyPem": new_public.decode("utf-8"),
                    "owner": actor_url,
                    "id": actor_url + "#main-key",
                },
            },
        )
        signed_request = factories["federation.SignedRequest"](
            auth__key=new_private,
            auth__key_id=actor_url + "#main-key",
            auth__headers=["date"],
        )
        prepared = signed_request.prepare()
        django_request = api_request.get(
            "/",
            **{
                "HTTP_DATE": prepared.headers["date"],
                "HTTP_SIGNATURE": prepared.headers["signature"],
            }
        )
        authenticator = authentication.SignatureAuthentication()
        user, _ = authenticator.authenticate(django_request)
        actor = django_request.actor
    
        assert user.is_anonymous is True
        assert actor.public_key == new_public.decode("utf-8")
        assert actor.fid == actor_url