diff --git a/api/funkwhale_api/federation/authentication.py b/api/funkwhale_api/federation/authentication.py
index f32c78ff30f00079d822bbf2921d2c4845fff5fc..d51679fc2cbe16fd408a223d9e8551ee9af744ba 100644
--- a/api/funkwhale_api/federation/authentication.py
+++ b/api/funkwhale_api/federation/authentication.py
@@ -19,6 +19,7 @@ class SignatureAuthentication(authentication.BaseAuthentication):
         try:
             actor = actors.get_actor(key_id.split("#")[0])
         except Exception as e:
+            raise
             raise exceptions.AuthenticationFailed(str(e))
 
         if not actor.public_key:
diff --git a/api/funkwhale_api/federation/jsonld.py b/api/funkwhale_api/federation/jsonld.py
index b19e775fd0872501021f785898e5505321535fde..5101faeb6bf33087a2b04b1384dbbf22d6026800 100644
--- a/api/funkwhale_api/federation/jsonld.py
+++ b/api/funkwhale_api/federation/jsonld.py
@@ -83,6 +83,7 @@ class Serializer(serializers.Serializer):
     id_source = None
     include_id = True
     include_type = True
+    valid_types = []
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -104,9 +105,27 @@ class Serializer(serializers.Serializer):
             )
 
     def run_validation(self, initial_data):
-        document = expand(initial_data)[0]
+        try:
+            document = expand(initial_data)[0]
+        except IndexError:
+            raise serializers.ValidationError(
+                "Cannot parse json-ld, maybe you are missing context."
+            )
         return super().run_validation(document)
 
+    def validate(self, validated_data):
+        validated_data = super().validate(validated_data)
+        if self.valid_types and "@type" in validated_data:
+            if validated_data["@type"] not in self.valid_types:
+                raise serializers.ValidationError(
+                    {
+                        "@type": "Invalid type. Allowed types are: {}".format(
+                            ", ".join(self.valid_types)
+                        )
+                    }
+                )
+        return validated_data
+
     def to_representation(self, data):
         data = super().to_representation(data)
         compacted = pyld.jsonld.compact(data, {"@context": ns.CONTEXTS})
diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 7c5454392d00de34047ea15e8e0aabd92b885403..d9229f6852fad80082b75b8a4e86b732475715b8 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -52,6 +52,13 @@ class PublicKeyField(jsonld.Serializer):
 class ActorSerializer(jsonld.Serializer):
     id_source = "url"
     type_source = "type_ap"
+    valid_types = [
+        ns.SHORT["as:Application"],
+        ns.SHORT["as:Group"],
+        ns.SHORT["as:Organization"],
+        ns.SHORT["as:Person"],
+        ns.SHORT["as:Service"],
+    ]
     jsonld_fields = [
         (
             ns.SHORT["as:outbox"],
@@ -119,8 +126,8 @@ class ActorSerializer(jsonld.Serializer):
             "url": self.validated_data["url"],
             "outbox_url": self.validated_data[ns.SHORT["as:outbox"]],
             "inbox_url": self.validated_data[ns.SHORT["ldp:inbox"]],
-            "following_url": self.validated_data[ns.SHORT["as:following"]],
-            "followers_url": self.validated_data[ns.SHORT["as:followers"]],
+            "following_url": self.validated_data.get(ns.SHORT["as:following"]),
+            "followers_url": self.validated_data.get(ns.SHORT["as:followers"]),
             "summary": self.validated_data.get(ns.SHORT["as:summary"]),
             "type": self.validated_data["type_ap"].split("#")[-1],
             "name": self.validated_data.get(ns.SHORT["as:name"]),
@@ -178,22 +185,22 @@ class APIActorSerializer(serializers.ModelSerializer):
 
 
 class LibraryActorSerializer(ActorSerializer):
-    url = serializers.ListField(child=serializers.JSONField())
+    # url = serializers.ListField(child=serializers.JSONField())
+    jsonld_fields = ActorSerializer.jsonld_fields + [
+        (
+            ns.SHORT["as:url"],
+            jsonld.Serializer(required=True),
+            {"source": "library_url"},
+        )
+    ]
 
     def validate(self, validated_data):
-        try:
-            urls = validated_data["url"]
-        except KeyError:
-            raise serializers.ValidationError("Missing URL field")
-
-        for u in urls:
-            try:
-                if u["name"] != "library":
-                    continue
-                validated_data["library_url"] = u["href"]
-                break
-            except KeyError:
+        validated_data = super().validate(validated_data)
+        for url in validated_data[ns.SHORT["as:url"]]:
+            if url[ns.SHORT["as:name"]][0]["@value"] != "library":
                 continue
+            validated_data["library_url"] = url[ns.SHORT["as:href"]][0]["@id"]
+            break
 
         return validated_data
 
diff --git a/api/tests/federation/test_authentication.py b/api/tests/federation/test_authentication.py
index 95cec5d2ac80d94a7b04de1dd5121c3d270b883b..e9371f010c0d5270460e49bbeeff670bb3895492 100644
--- a/api/tests/federation/test_authentication.py
+++ b/api/tests/federation/test_authentication.py
@@ -1,4 +1,4 @@
-from funkwhale_api.federation import authentication, keys
+from funkwhale_api.federation import authentication, keys, ns
 
 
 def test_authenticate(factories, mocker, api_request):
@@ -7,10 +7,13 @@ def test_authenticate(factories, mocker, api_request):
     mocker.patch(
         "funkwhale_api.federation.actors.get_actor_data",
         return_value={
+            "@context": ns.CONTEXTS,
             "id": actor_url,
             "type": "Person",
             "outbox": "https://test.com",
             "inbox": "https://test.com",
+            "following": "https://test.com",
+            "followers": "https://test.com",
             "preferredUsername": "test",
             "publicKey": {
                 "publicKeyPem": public.decode("utf-8"),
diff --git a/api/tests/federation/test_jsonld.py b/api/tests/federation/test_jsonld.py
index a8681006e3ab79b1d059999c03540fc4577c0140..7d6712ac58afdee34424a6f14e66ccab9eab4164 100644
--- a/api/tests/federation/test_jsonld.py
+++ b/api/tests/federation/test_jsonld.py
@@ -93,6 +93,37 @@ def test_json_ld_serializer_validation_id(field_conf, expected):
     }
 
 
+def test_json_ld_validates_type_failing():
+    document = {
+        "@context": ns.NS["as"]["documentUrl"],
+        "type": "Disallowed",
+        "outbox": "http://test",
+        "id": "http://test.document",
+    }
+
+    class Serializer(jsonld.Serializer):
+        valid_types = [ns.SHORT["as:Person"]]
+
+    serializer = Serializer(data=document)
+    assert serializer.is_valid() is False
+    assert "@type" in serializer.errors
+
+
+def test_json_ld_validates_type_success():
+    document = {
+        "@context": ns.NS["as"]["documentUrl"],
+        "type": "Person",
+        "outbox": "http://test",
+        "id": "http://test.document",
+    }
+
+    class Serializer(jsonld.Serializer):
+        valid_types = [ns.SHORT["as:Person"]]
+
+    serializer = Serializer(data=document)
+    assert serializer.is_valid(raise_exception=True) is True
+
+
 def test_json_ld_serializer_to_representation():
     class Serializer(jsonld.Serializer):
         jsonld_fields = [