diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
index 8adf2b1840143fd729de7b59f12e0c756f5a3655..94852a52d588946b1a3cf6b495bbb31e44d8623d 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/keycloak.py
@@ -48,7 +48,7 @@ def get_users_by_role_in_project(role, project):
     if project in project_persons:
         return project_persons[project][role]
     else:
-        []
+        return []
 
 
 @cachetools.func.ttl_cache(ttl=600)
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
index effe24b408c55dbd4b1151971f61b079c35d1281..914f7dd9e15d534f567382535576a09064e06323 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/permissions.py
@@ -28,7 +28,8 @@ def get_project_roles_for_user(user):
         try:
             if user == models.User.objects.get(username='paulus'):
                 return ({'project': 'test_user_is_shared_support', 'role': 'shared_support'},
-                        {'project': 'test_user_is_contact', 'role': 'contact'})
+                        {'project': 'test_user_is_contact', 'role': 'contact'},
+                        {'project': 'test_user_is_friend', 'role': 'friend_of_project'})
         except:
             pass
 
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
index 7bfb0f1a186c72099d037c16b8268377ebe254a3..1f4defdc79838614333a9dbb20f9a1b8a8b98e2d 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py
@@ -27,6 +27,7 @@ from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet, LOF
 from lofar.sas.tmss.tmss.tmssapp import models
 from lofar.sas.tmss.tmss.tmssapp import serializers
 from lofar.sas.tmss.tmss.tmssapp.adapters.reports import create_cycle_report, create_project_report
+from lofar.sas.tmss.tmss.tmssapp.adapters.keycloak import get_users_by_role_in_project
 from django.http import JsonResponse
 
 from datetime import datetime
@@ -34,7 +35,7 @@ from lofar.common.json_utils import get_default_json_object_for_schema
 from lofar.common.datetimeutils import formatDatetime
 from lofar.sas.tmss.tmss.tmssapp.tasks import *
 from lofar.sas.tmss.tmss.tmssapp.subtasks import *
-from lofar.sas.tmss.tmss.tmssapp.viewsets.permissions import TMSSDjangoModelPermissions
+from lofar.sas.tmss.tmss.tmssapp.viewsets.permissions import TMSSDjangoModelPermissions, get_project_roles_for_user
 
 from django.urls  import resolve, get_script_prefix,Resolver404
 from rest_framework.filters import OrderingFilter
@@ -434,6 +435,28 @@ class ProjectViewSet(LOFARViewSet):
             return Response('Error: workflowapp is not running. It is needed to retrieve some reporting information.', status=status.HTTP_503_SERVICE_UNAVAILABLE)
         return Response(result, status=status.HTTP_200_OK)
 
+    @swagger_auto_schema(responses={200: 'List of users that have the "friend of project" role for this project',
+                                    403: 'forbidden'},
+                         operation_description="Get the list of users that have the 'friend of project' role for this project")
+    @action(methods=['get'], detail=True, url_name="friend", name="Friend(s) of this project")
+    def friend(self, request, pk=None):
+        project = get_object_or_404(models.Project, pk=pk)
+        result = get_users_by_role_in_project(models.ProjectRole.Choices.FRIEND_OF_PROJECT.value, project.name)
+        return Response(result, status=status.HTTP_200_OK)
+
+    @swagger_auto_schema(responses={200: 'List of roles that the requesting user has in this project',
+                                    403: 'forbidden'},
+                         operation_description="Get the list of roles that the requesting user has in this project")
+    @action(methods=['get'], detail=True, url_name="my_roles", name="My roles in this project")
+    def my_roles(self, request, pk=None):
+        project = get_object_or_404(models.Project, pk=pk)
+        project_roles = get_project_roles_for_user(request.user)
+        result = []
+        for project_role in project_roles:
+            if project.name == project_role['project']:
+                result.append(project_role['role'])
+        return Response(result, status=status.HTTP_200_OK)
+
 
 class ProjectNestedViewSet(LOFARNestedViewSet):
     queryset = models.Project.objects.all()
diff --git a/SAS/TMSS/backend/test/t_permissions_project_roles.py b/SAS/TMSS/backend/test/t_permissions_project_roles.py
index 40ec90a4850a149636986c3eccbedb49c606b6bb..0c5db12f20f9ba7b394b995e841f59dcd1aa1bb1 100755
--- a/SAS/TMSS/backend/test/t_permissions_project_roles.py
+++ b/SAS/TMSS/backend/test/t_permissions_project_roles.py
@@ -51,6 +51,13 @@ from lofar.sas.tmss.test.tmss_test_data_rest import TMSSRESTTestDataCreator
 
 from django.test import TestCase
 
+from django.contrib.auth import get_user_model
+User = get_user_model()
+
+from django.conf import settings
+
+import json
+
 class ProjectPermissionTestCase(TestCase):
     # This tests that the project permissions are enforced in light of the project roles that are externally provided
     # for the user through the user admin. This test does not rely on the project permissions as defined in the system,
@@ -66,7 +73,8 @@ class ProjectPermissionTestCase(TestCase):
         cls.project_permission_patcher = mock.patch('lofar.sas.tmss.tmss.tmssapp.viewsets.get_project_roles_for_user')  # todo: fix namespace so we get the get_project_roles that gets actually used
         cls.project_permission_mock = cls.project_permission_patcher.start()
         cls.project_permission_mock.return_value = ({'project': 'test_user_is_shared_support', 'role': 'shared_support'},
-                                                    {'project': 'test_user_is_contact', 'role': 'contact_author'})
+                                                    {'project': 'test_user_is_contact', 'role': 'contact_author'},
+                                                    {'project': 'test_user_is_friend', 'role': 'friend_of_project'})
 
         # create some stuff as the standard super user, as setup for the tests below
         cls.test_data_creator = TMSSRESTTestDataCreator(BASE_URL, AUTH)
@@ -75,8 +83,9 @@ class ProjectPermissionTestCase(TestCase):
         # create projects with magic names for which permission exists (or which have no whitelisted generic name)
         cls.project_shared_support_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.Project(name='test_user_is_shared_support', cycle_urls=[cycle_url]), '/project/')
         cls.project_contact_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.Project(name='test_user_is_contact', cycle_urls=[cycle_url]), '/project/')
+        cls.project_friend_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.Project(name='test_user_is_friend', cycle_urls=[cycle_url]), '/project/')
         cls.project_forbidden_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.Project(name='forbidden', cycle_urls=[cycle_url]), '/project/')
-
+        cls.project_keycloak_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.Project(name="2014LOFAROBS", cycle_urls=[cycle_url]), '/project/')  # project is known to Keycloak
 
         # user is shared_support
         cls.scheduling_set_shared_support_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.SchedulingSet(project_url=cls.project_shared_support_url), '/scheduling_set/')
@@ -92,8 +101,10 @@ class ProjectPermissionTestCase(TestCase):
 
         # create the required permission entries to control what endpoint action requires which project role
         shared_support_role_url = BASE_URL + '/project_role/shared_support/'
+        friend_of_project_role_url = BASE_URL + '/project_role/friend_of_project/'
         cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.ProjectPermission(name='taskdraft', GET=[shared_support_role_url], POST=[shared_support_role_url]), '/project_permission/')
         cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.ProjectPermission(name='taskdraft-create_task_blueprint', POST=[shared_support_role_url]), '/project_permission/')
+        cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.ProjectPermission(name='project-my_roles', GET=[shared_support_role_url, friend_of_project_role_url]), '/project_permission/')
 
         cls.task_template_url = cls.test_data_creator.post_data_and_get_url(cls.test_data_creator.TaskTemplate(), '/task_template/')
 
@@ -228,7 +239,44 @@ class ProjectPermissionTestCase(TestCase):
             self.assertEqual(r.status_code, 403)
             self.assertNotIn('Access-Control-Allow-Methods', r.headers)
 
-    # todo: add tests for other models with project permissions
+    def test_project_get_friend_returns_correct_user(self):
+        """
+        Note: This test relies on real data from Keycloak.
+        """
+        with requests.Session() as session:
+            session.verify = False
+            session.auth = (AUTH.username, AUTH.password)
+            r = session.get(self.project_keycloak_url + '/friend/')
+        if 'Invalid user credentials' in str(r.content) or \
+                'Service Unavailable' in str(r.content):
+            self.skipTest('skipping test_project_get_friend_returns_correct_user because the test environment has'
+                           'no valid admin credentials configured, or Keycloak is not working correctly.')
+        self.assertEqual(r.status_code, 200)
+        content = json.loads(r.content.decode('utf-8'))
+        self.assertEqual(len(content), 2)
+        for friend in content:
+            # Todo: find a way to mock the Keycloak response so we can assert more strictly.
+            self.assertTrue(friend.endswith('@astron.nl'))  # redacted expected full email due to GDPR
+
+    def test_project_get_friend_returns_403_if_no_permission_for_project(self):
+
+        r = GET_and_assert_equal_expected_code(self, self.project_forbidden_url + '/friend/', 403, auth=self.auth)
+        self.assertIn('permission', str(r))
+
+    def test_project_get_my_roles_returns_correct_roles(self):
+
+        r = GET_and_assert_equal_expected_code(self, self.project_shared_support_url + '/my_roles/', 200, auth=self.auth)
+        expected_reply = ['shared_support']
+        self.assertEqual(expected_reply, r)
+
+        r = GET_and_assert_equal_expected_code(self, self.project_friend_url + '/my_roles/', 200, auth=self.auth)
+        expected_reply = ['friend_of_project']
+        self.assertEqual(expected_reply, r)
+
+    def test_project_get_my_roles_returns_403_if_no_permission_for_project(self):
+
+        r = GET_and_assert_equal_expected_code(self, self.project_forbidden_url + '/my_roles/', 403, auth=self.auth)
+        self.assertIn('permission', str(r))
 
 
 if __name__ == "__main__":