diff --git a/openlobby/core/api/types.py b/openlobby/core/api/types.py
index 3071b18cfe0bcc62457dc8c933e4c13d856300d8..d9d64e9679052172e9a4ebec83152020ad2f755f 100644
--- a/openlobby/core/api/types.py
+++ b/openlobby/core/api/types.py
@@ -108,6 +108,50 @@ class User(graphene.ObjectType):
         return ReportConnection(page_info=page_info, edges=edges, total_count=total)
 
 
+class Author(graphene.ObjectType):
+    name = graphene.String()
+    openid_uid = graphene.String()
+    extra = JSONString()
+    # TODO
+    # reports = relay.ConnectionField(ReportConnection)
+
+    class Meta:
+        interfaces = (relay.Node, )
+
+    @classmethod
+    def from_db(cls, user):
+        return cls(
+            id=user.id,
+            name=user.get_full_name(),
+            openid_uid=user.openid_uid,
+            extra=user.extra,
+        )
+
+    @classmethod
+    def get_node(cls, info, id):
+        try:
+            return cls.from_db(models.User.objects.get(id=id, is_author=True))
+        except models.User.DoesNotExist:
+            return None
+
+    # TODO
+    """
+    def resolve_reports(self, info, **kwargs):
+        paginator = Paginator(**kwargs)
+        response = search.reports_by_author(self.id, paginator, **info.context)
+        total = response.hits.total
+        page_info = paginator.get_page_info(total)
+
+        edges = []
+        for i, report in enumerate(response):
+            cursor = paginator.get_edge_cursor(i + 1)
+            node = Report.from_es(report, author=self)
+            edges.append(ReportConnection.Edge(node=node, cursor=cursor))
+
+        return ReportConnection(page_info=page_info, edges=edges, total_count=total)
+    """
+
+
 class LoginShortcut(graphene.ObjectType):
     name = graphene.String()
 
diff --git a/openlobby/core/tests/snapshots/snap_test_schema.py b/openlobby/core/tests/snapshots/snap_test_schema.py
index f226461427583f01b2d025cce653a97aa3e1734e..d5d9f5a4d31c858202ba893b12e8712e63c26804 100644
--- a/openlobby/core/tests/snapshots/snap_test_schema.py
+++ b/openlobby/core/tests/snapshots/snap_test_schema.py
@@ -12,3 +12,7 @@ snapshots['test_login_shortcuts__none 1'] = b'{"data":{"loginShortcuts":[]}}'
 snapshots['test_login_shortcuts 1'] = b'{"data":{"loginShortcuts":[{"id":"TG9naW5TaG9ydGN1dDoyMA==","name":"bar"}]}}'
 
 snapshots['test_node__login_shortcut 1'] = b'{"data":{"node":{"id":"TG9naW5TaG9ydGN1dDoxMA==","name":"foo"}}}'
+
+snapshots['test_node__author 1'] = b'{"data":{"node":{"id":"QXV0aG9yOjU=","name":"Winston Wolfe","openidUid":"TheWolf","extra":"{\\"x\\": 1}"}}}'
+
+snapshots['test_node__author__only_if_is_author 1'] = b'{"data":{"node":null}}'
diff --git a/openlobby/core/tests/test_schema.py b/openlobby/core/tests/test_schema.py
index cfd5bd2364b62d9579473292455c6bf2fe2cbdb1..469ac14e7dd34c2f6e870be27ca4f95cdad8b7ab 100644
--- a/openlobby/core/tests/test_schema.py
+++ b/openlobby/core/tests/test_schema.py
@@ -1,7 +1,7 @@
 import pytest
 from graphql_relay import to_global_id
 
-from ..models import OpenIdClient
+from ..models import OpenIdClient, User
 
 
 @pytest.mark.django_db
@@ -47,3 +47,46 @@ def test_node__login_shortcut(client, snapshot):
     }}
     """.format(id=to_global_id('LoginShortcut', 10))})
     snapshot.assert_match(res.content)
+
+
+@pytest.mark.django_db
+def test_node__author(client, snapshot):
+    User.objects.create(
+        id=5,
+        is_author=True,
+        openid_uid='TheWolf',
+        first_name='Winston',
+        last_name='Wolfe',
+        extra={'x': 1},
+    )
+    res = client.post('/graphql', {'query': """
+    query {{
+        node (id:"{id}") {{
+            ... on Author {{
+                id
+                name
+                openidUid
+                extra
+            }}
+        }}
+    }}
+    """.format(id=to_global_id('Author', 5))})
+    snapshot.assert_match(res.content)
+
+
+@pytest.mark.django_db
+def test_node__author__only_if_is_author(client, snapshot):
+    User.objects.create(
+        id=7,
+        is_author=False,
+    )
+    res = client.post('/graphql', {'query': """
+    query {{
+        node (id:"{id}") {{
+            ... on Author {{
+                id
+            }}
+        }}
+    }}
+    """.format(id=to_global_id('Author', 7))})
+    snapshot.assert_match(res.content)
diff --git a/openlobby/schema.py b/openlobby/schema.py
index 6a526d507220b0cf8a410b61d23f869595c5abb3..5772e2fd8a448384edf4b427c50b69aaa3c3ca41 100644
--- a/openlobby/schema.py
+++ b/openlobby/schema.py
@@ -2,7 +2,7 @@ import graphene
 
 from openlobby.core.api.mutations import Mutation as CoreMutation
 from openlobby.core.api.schema import Query as CoreQuery
-from openlobby.core.api.types import User, Report, LoginShortcut
+from openlobby.core.api.types import Author, User, Report, LoginShortcut
 
 
 class Query(CoreQuery, graphene.ObjectType):
@@ -14,4 +14,4 @@ class Mutation(CoreMutation, graphene.ObjectType):
 
 
 schema = graphene.Schema(query=Query, mutation=Mutation,
-    types=[User, Report, LoginShortcut])
+    types=[Author, User, Report, LoginShortcut])