authentik.core.tests.test_applications_api

Test Applications API

  1"""Test Applications API"""
  2
  3from json import loads
  4
  5from django.urls import reverse
  6from rest_framework.test import APITestCase
  7
  8from authentik.core.models import Application
  9from authentik.core.tests.utils import create_test_admin_user, create_test_flow
 10from authentik.lib.generators import generate_id
 11from authentik.policies.dummy.models import DummyPolicy
 12from authentik.policies.models import PolicyBinding
 13from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode
 14from authentik.providers.proxy.models import ProxyProvider
 15from authentik.providers.saml.models import SAMLProvider
 16
 17
 18class TestApplicationsAPI(APITestCase):
 19    """Test applications API"""
 20
 21    def setUp(self) -> None:
 22        self.user = create_test_admin_user()
 23        self.provider = OAuth2Provider.objects.create(
 24            name="test",
 25            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://some-other-domain")],
 26            authorization_flow=create_test_flow(),
 27        )
 28        self.allowed: Application = Application.objects.create(
 29            name="allowed",
 30            slug="allowed",
 31            meta_launch_url="https://goauthentik.io/%(username)s",
 32            open_in_new_tab=True,
 33            provider=self.provider,
 34        )
 35        self.denied = Application.objects.create(name="denied", slug="denied")
 36        PolicyBinding.objects.create(
 37            target=self.denied,
 38            policy=DummyPolicy.objects.create(name="deny", result=False, wait_min=1, wait_max=2),
 39            order=0,
 40        )
 41
 42    def test_formatted_launch_url(self):
 43        """Test formatted launch URL"""
 44        self.client.force_login(self.user)
 45        self.assertEqual(
 46            self.client.patch(
 47                reverse("authentik_api:application-detail", kwargs={"slug": self.allowed.slug}),
 48                {"meta_launch_url": "https://%(username)s-test.test.goauthentik.io/%(username)s"},
 49            ).status_code,
 50            200,
 51        )
 52        self.allowed.refresh_from_db()
 53        self.assertEqual(
 54            self.allowed.get_launch_url(self.user),
 55            f"https://{self.user.username}-test.test.goauthentik.io/{self.user.username}",
 56        )
 57
 58    def test_check_access(self):
 59        """Test check_access operation"""
 60        self.client.force_login(self.user)
 61        response = self.client.get(
 62            reverse(
 63                "authentik_api:application-check-access",
 64                kwargs={"slug": self.allowed.slug},
 65            )
 66        )
 67        self.assertEqual(response.status_code, 200)
 68        body = loads(response.content.decode())
 69        self.assertEqual(body["passing"], True)
 70        self.assertEqual(body["messages"], [])
 71        self.assertEqual(len(body["log_messages"]), 0)
 72        response = self.client.get(
 73            reverse(
 74                "authentik_api:application-check-access",
 75                kwargs={"slug": self.denied.slug},
 76            )
 77        )
 78        self.assertEqual(response.status_code, 200)
 79        body = loads(response.content.decode())
 80        self.assertEqual(body["passing"], False)
 81        self.assertEqual(body["messages"], ["dummy"])
 82
 83    def test_list(self):
 84        """Test list operation without superuser_full_list"""
 85        self.client.force_login(self.user)
 86        response = self.client.get(reverse("authentik_api:application-list"))
 87        self.assertJSONEqual(
 88            response.content.decode(),
 89            {
 90                "autocomplete": {},
 91                "pagination": {
 92                    "next": 0,
 93                    "previous": 0,
 94                    "count": 2,
 95                    "current": 1,
 96                    "total_pages": 1,
 97                    "start_index": 1,
 98                    "end_index": 2,
 99                },
100                "results": [
101                    {
102                        "pk": str(self.allowed.pk),
103                        "name": "allowed",
104                        "slug": "allowed",
105                        "group": "",
106                        "provider": self.provider.pk,
107                        "provider_obj": {
108                            "assigned_application_name": "allowed",
109                            "assigned_application_slug": "allowed",
110                            "assigned_backchannel_application_name": None,
111                            "assigned_backchannel_application_slug": None,
112                            "authentication_flow": None,
113                            "invalidation_flow": None,
114                            "authorization_flow": str(self.provider.authorization_flow.pk),
115                            "component": "ak-provider-oauth2-form",
116                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
117                            "name": self.provider.name,
118                            "pk": self.provider.pk,
119                            "property_mappings": [],
120                            "verbose_name": "OAuth2/OpenID Provider",
121                            "verbose_name_plural": "OAuth2/OpenID Providers",
122                        },
123                        "backchannel_providers": [],
124                        "backchannel_providers_obj": [],
125                        "launch_url": f"https://goauthentik.io/{self.user.username}",
126                        "meta_launch_url": "https://goauthentik.io/%(username)s",
127                        "open_in_new_tab": True,
128                        "meta_icon": "",
129                        "meta_icon_url": None,
130                        "meta_icon_themed_urls": None,
131                        "meta_description": "",
132                        "meta_publisher": "",
133                        "policy_engine_mode": "any",
134                    },
135                ],
136            },
137        )
138
139    def test_list_superuser_full_list(self):
140        """Test list operation with superuser_full_list"""
141        self.client.force_login(self.user)
142        response = self.client.get(
143            reverse("authentik_api:application-list") + "?superuser_full_list=true"
144        )
145        self.assertJSONEqual(
146            response.content.decode(),
147            {
148                "autocomplete": {},
149                "pagination": {
150                    "next": 0,
151                    "previous": 0,
152                    "count": 2,
153                    "current": 1,
154                    "total_pages": 1,
155                    "start_index": 1,
156                    "end_index": 2,
157                },
158                "results": [
159                    {
160                        "pk": str(self.allowed.pk),
161                        "name": "allowed",
162                        "slug": "allowed",
163                        "group": "",
164                        "provider": self.provider.pk,
165                        "provider_obj": {
166                            "assigned_application_name": "allowed",
167                            "assigned_application_slug": "allowed",
168                            "assigned_backchannel_application_name": None,
169                            "assigned_backchannel_application_slug": None,
170                            "authentication_flow": None,
171                            "invalidation_flow": None,
172                            "authorization_flow": str(self.provider.authorization_flow.pk),
173                            "component": "ak-provider-oauth2-form",
174                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
175                            "name": self.provider.name,
176                            "pk": self.provider.pk,
177                            "property_mappings": [],
178                            "verbose_name": "OAuth2/OpenID Provider",
179                            "verbose_name_plural": "OAuth2/OpenID Providers",
180                        },
181                        "backchannel_providers": [],
182                        "backchannel_providers_obj": [],
183                        "launch_url": f"https://goauthentik.io/{self.user.username}",
184                        "meta_launch_url": "https://goauthentik.io/%(username)s",
185                        "open_in_new_tab": True,
186                        "meta_icon": "",
187                        "meta_icon_url": None,
188                        "meta_icon_themed_urls": None,
189                        "meta_description": "",
190                        "meta_publisher": "",
191                        "policy_engine_mode": "any",
192                    },
193                    {
194                        "launch_url": None,
195                        "meta_description": "",
196                        "meta_icon": "",
197                        "meta_icon_url": None,
198                        "meta_icon_themed_urls": None,
199                        "meta_launch_url": "",
200                        "open_in_new_tab": False,
201                        "meta_publisher": "",
202                        "group": "",
203                        "name": "denied",
204                        "pk": str(self.denied.pk),
205                        "policy_engine_mode": "any",
206                        "provider": None,
207                        "provider_obj": None,
208                        "backchannel_providers": [],
209                        "backchannel_providers_obj": [],
210                        "slug": "denied",
211                    },
212                ],
213            },
214        )
215
216    def test_get_provider(self):
217        """Ensure that proxy providers (at the time of writing that is the only provider
218        that inherits from another proxy type (OAuth) instead of inheriting from the root
219        provider class) is correctly looked up and selected from the database"""
220        slug = generate_id()
221        provider = ProxyProvider.objects.create(name=generate_id())
222        Application.objects.create(
223            name=generate_id(),
224            slug=slug,
225            provider=provider,
226        )
227        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
228        self.assertEqual(
229            Application.objects.with_provider().get(slug=slug).get_provider(), provider
230        )
231
232        slug = generate_id()
233        provider = SAMLProvider.objects.create(name=generate_id())
234        Application.objects.create(
235            name=generate_id(),
236            slug=slug,
237            provider=provider,
238        )
239        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
240        self.assertEqual(
241            Application.objects.with_provider().get(slug=slug).get_provider(), provider
242        )
243
244    def test_create_application_with_reserved_slug(self):
245        """Test creating an application with a reserved slug"""
246        self.client.force_login(self.user)
247        response = self.client.post(
248            reverse("authentik_api:application-list"),
249            {
250                "name": "Test Application",
251                "slug": Application.reserved_slugs[0],
252            },
253        )
254        self.assertEqual(response.status_code, 400)
255        self.assertIn("slug", response.data)
256        self.assertIn("reserved", response.data["slug"][0])
257
258    def test_update_application_with_reserved_slug(self):
259        """Test updating an application to use a reserved slug"""
260        self.client.force_login(self.user)
261        app = Application.objects.create(
262            name="Test Application",
263            slug="valid-slug",
264        )
265
266        response = self.client.patch(
267            reverse("authentik_api:application-detail", kwargs={"slug": app.slug}),
268            {
269                "slug": Application.reserved_slugs[0],
270            },
271        )
272        self.assertEqual(response.status_code, 400)
273        self.assertIn("slug", response.data)
274        self.assertIn("reserved", response.data["slug"][0])
class TestApplicationsAPI(rest_framework.test.APITestCase):
 19class TestApplicationsAPI(APITestCase):
 20    """Test applications API"""
 21
 22    def setUp(self) -> None:
 23        self.user = create_test_admin_user()
 24        self.provider = OAuth2Provider.objects.create(
 25            name="test",
 26            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://some-other-domain")],
 27            authorization_flow=create_test_flow(),
 28        )
 29        self.allowed: Application = Application.objects.create(
 30            name="allowed",
 31            slug="allowed",
 32            meta_launch_url="https://goauthentik.io/%(username)s",
 33            open_in_new_tab=True,
 34            provider=self.provider,
 35        )
 36        self.denied = Application.objects.create(name="denied", slug="denied")
 37        PolicyBinding.objects.create(
 38            target=self.denied,
 39            policy=DummyPolicy.objects.create(name="deny", result=False, wait_min=1, wait_max=2),
 40            order=0,
 41        )
 42
 43    def test_formatted_launch_url(self):
 44        """Test formatted launch URL"""
 45        self.client.force_login(self.user)
 46        self.assertEqual(
 47            self.client.patch(
 48                reverse("authentik_api:application-detail", kwargs={"slug": self.allowed.slug}),
 49                {"meta_launch_url": "https://%(username)s-test.test.goauthentik.io/%(username)s"},
 50            ).status_code,
 51            200,
 52        )
 53        self.allowed.refresh_from_db()
 54        self.assertEqual(
 55            self.allowed.get_launch_url(self.user),
 56            f"https://{self.user.username}-test.test.goauthentik.io/{self.user.username}",
 57        )
 58
 59    def test_check_access(self):
 60        """Test check_access operation"""
 61        self.client.force_login(self.user)
 62        response = self.client.get(
 63            reverse(
 64                "authentik_api:application-check-access",
 65                kwargs={"slug": self.allowed.slug},
 66            )
 67        )
 68        self.assertEqual(response.status_code, 200)
 69        body = loads(response.content.decode())
 70        self.assertEqual(body["passing"], True)
 71        self.assertEqual(body["messages"], [])
 72        self.assertEqual(len(body["log_messages"]), 0)
 73        response = self.client.get(
 74            reverse(
 75                "authentik_api:application-check-access",
 76                kwargs={"slug": self.denied.slug},
 77            )
 78        )
 79        self.assertEqual(response.status_code, 200)
 80        body = loads(response.content.decode())
 81        self.assertEqual(body["passing"], False)
 82        self.assertEqual(body["messages"], ["dummy"])
 83
 84    def test_list(self):
 85        """Test list operation without superuser_full_list"""
 86        self.client.force_login(self.user)
 87        response = self.client.get(reverse("authentik_api:application-list"))
 88        self.assertJSONEqual(
 89            response.content.decode(),
 90            {
 91                "autocomplete": {},
 92                "pagination": {
 93                    "next": 0,
 94                    "previous": 0,
 95                    "count": 2,
 96                    "current": 1,
 97                    "total_pages": 1,
 98                    "start_index": 1,
 99                    "end_index": 2,
100                },
101                "results": [
102                    {
103                        "pk": str(self.allowed.pk),
104                        "name": "allowed",
105                        "slug": "allowed",
106                        "group": "",
107                        "provider": self.provider.pk,
108                        "provider_obj": {
109                            "assigned_application_name": "allowed",
110                            "assigned_application_slug": "allowed",
111                            "assigned_backchannel_application_name": None,
112                            "assigned_backchannel_application_slug": None,
113                            "authentication_flow": None,
114                            "invalidation_flow": None,
115                            "authorization_flow": str(self.provider.authorization_flow.pk),
116                            "component": "ak-provider-oauth2-form",
117                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
118                            "name": self.provider.name,
119                            "pk": self.provider.pk,
120                            "property_mappings": [],
121                            "verbose_name": "OAuth2/OpenID Provider",
122                            "verbose_name_plural": "OAuth2/OpenID Providers",
123                        },
124                        "backchannel_providers": [],
125                        "backchannel_providers_obj": [],
126                        "launch_url": f"https://goauthentik.io/{self.user.username}",
127                        "meta_launch_url": "https://goauthentik.io/%(username)s",
128                        "open_in_new_tab": True,
129                        "meta_icon": "",
130                        "meta_icon_url": None,
131                        "meta_icon_themed_urls": None,
132                        "meta_description": "",
133                        "meta_publisher": "",
134                        "policy_engine_mode": "any",
135                    },
136                ],
137            },
138        )
139
140    def test_list_superuser_full_list(self):
141        """Test list operation with superuser_full_list"""
142        self.client.force_login(self.user)
143        response = self.client.get(
144            reverse("authentik_api:application-list") + "?superuser_full_list=true"
145        )
146        self.assertJSONEqual(
147            response.content.decode(),
148            {
149                "autocomplete": {},
150                "pagination": {
151                    "next": 0,
152                    "previous": 0,
153                    "count": 2,
154                    "current": 1,
155                    "total_pages": 1,
156                    "start_index": 1,
157                    "end_index": 2,
158                },
159                "results": [
160                    {
161                        "pk": str(self.allowed.pk),
162                        "name": "allowed",
163                        "slug": "allowed",
164                        "group": "",
165                        "provider": self.provider.pk,
166                        "provider_obj": {
167                            "assigned_application_name": "allowed",
168                            "assigned_application_slug": "allowed",
169                            "assigned_backchannel_application_name": None,
170                            "assigned_backchannel_application_slug": None,
171                            "authentication_flow": None,
172                            "invalidation_flow": None,
173                            "authorization_flow": str(self.provider.authorization_flow.pk),
174                            "component": "ak-provider-oauth2-form",
175                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
176                            "name": self.provider.name,
177                            "pk": self.provider.pk,
178                            "property_mappings": [],
179                            "verbose_name": "OAuth2/OpenID Provider",
180                            "verbose_name_plural": "OAuth2/OpenID Providers",
181                        },
182                        "backchannel_providers": [],
183                        "backchannel_providers_obj": [],
184                        "launch_url": f"https://goauthentik.io/{self.user.username}",
185                        "meta_launch_url": "https://goauthentik.io/%(username)s",
186                        "open_in_new_tab": True,
187                        "meta_icon": "",
188                        "meta_icon_url": None,
189                        "meta_icon_themed_urls": None,
190                        "meta_description": "",
191                        "meta_publisher": "",
192                        "policy_engine_mode": "any",
193                    },
194                    {
195                        "launch_url": None,
196                        "meta_description": "",
197                        "meta_icon": "",
198                        "meta_icon_url": None,
199                        "meta_icon_themed_urls": None,
200                        "meta_launch_url": "",
201                        "open_in_new_tab": False,
202                        "meta_publisher": "",
203                        "group": "",
204                        "name": "denied",
205                        "pk": str(self.denied.pk),
206                        "policy_engine_mode": "any",
207                        "provider": None,
208                        "provider_obj": None,
209                        "backchannel_providers": [],
210                        "backchannel_providers_obj": [],
211                        "slug": "denied",
212                    },
213                ],
214            },
215        )
216
217    def test_get_provider(self):
218        """Ensure that proxy providers (at the time of writing that is the only provider
219        that inherits from another proxy type (OAuth) instead of inheriting from the root
220        provider class) is correctly looked up and selected from the database"""
221        slug = generate_id()
222        provider = ProxyProvider.objects.create(name=generate_id())
223        Application.objects.create(
224            name=generate_id(),
225            slug=slug,
226            provider=provider,
227        )
228        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
229        self.assertEqual(
230            Application.objects.with_provider().get(slug=slug).get_provider(), provider
231        )
232
233        slug = generate_id()
234        provider = SAMLProvider.objects.create(name=generate_id())
235        Application.objects.create(
236            name=generate_id(),
237            slug=slug,
238            provider=provider,
239        )
240        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
241        self.assertEqual(
242            Application.objects.with_provider().get(slug=slug).get_provider(), provider
243        )
244
245    def test_create_application_with_reserved_slug(self):
246        """Test creating an application with a reserved slug"""
247        self.client.force_login(self.user)
248        response = self.client.post(
249            reverse("authentik_api:application-list"),
250            {
251                "name": "Test Application",
252                "slug": Application.reserved_slugs[0],
253            },
254        )
255        self.assertEqual(response.status_code, 400)
256        self.assertIn("slug", response.data)
257        self.assertIn("reserved", response.data["slug"][0])
258
259    def test_update_application_with_reserved_slug(self):
260        """Test updating an application to use a reserved slug"""
261        self.client.force_login(self.user)
262        app = Application.objects.create(
263            name="Test Application",
264            slug="valid-slug",
265        )
266
267        response = self.client.patch(
268            reverse("authentik_api:application-detail", kwargs={"slug": app.slug}),
269            {
270                "slug": Application.reserved_slugs[0],
271            },
272        )
273        self.assertEqual(response.status_code, 400)
274        self.assertIn("slug", response.data)
275        self.assertIn("reserved", response.data["slug"][0])

Test applications API

def setUp(self) -> None:
22    def setUp(self) -> None:
23        self.user = create_test_admin_user()
24        self.provider = OAuth2Provider.objects.create(
25            name="test",
26            redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://some-other-domain")],
27            authorization_flow=create_test_flow(),
28        )
29        self.allowed: Application = Application.objects.create(
30            name="allowed",
31            slug="allowed",
32            meta_launch_url="https://goauthentik.io/%(username)s",
33            open_in_new_tab=True,
34            provider=self.provider,
35        )
36        self.denied = Application.objects.create(name="denied", slug="denied")
37        PolicyBinding.objects.create(
38            target=self.denied,
39            policy=DummyPolicy.objects.create(name="deny", result=False, wait_min=1, wait_max=2),
40            order=0,
41        )

Hook method for setting up the test fixture before exercising it.

def test_formatted_launch_url(self):
43    def test_formatted_launch_url(self):
44        """Test formatted launch URL"""
45        self.client.force_login(self.user)
46        self.assertEqual(
47            self.client.patch(
48                reverse("authentik_api:application-detail", kwargs={"slug": self.allowed.slug}),
49                {"meta_launch_url": "https://%(username)s-test.test.goauthentik.io/%(username)s"},
50            ).status_code,
51            200,
52        )
53        self.allowed.refresh_from_db()
54        self.assertEqual(
55            self.allowed.get_launch_url(self.user),
56            f"https://{self.user.username}-test.test.goauthentik.io/{self.user.username}",
57        )

Test formatted launch URL

def test_check_access(self):
59    def test_check_access(self):
60        """Test check_access operation"""
61        self.client.force_login(self.user)
62        response = self.client.get(
63            reverse(
64                "authentik_api:application-check-access",
65                kwargs={"slug": self.allowed.slug},
66            )
67        )
68        self.assertEqual(response.status_code, 200)
69        body = loads(response.content.decode())
70        self.assertEqual(body["passing"], True)
71        self.assertEqual(body["messages"], [])
72        self.assertEqual(len(body["log_messages"]), 0)
73        response = self.client.get(
74            reverse(
75                "authentik_api:application-check-access",
76                kwargs={"slug": self.denied.slug},
77            )
78        )
79        self.assertEqual(response.status_code, 200)
80        body = loads(response.content.decode())
81        self.assertEqual(body["passing"], False)
82        self.assertEqual(body["messages"], ["dummy"])

Test check_access operation

def test_list(self):
 84    def test_list(self):
 85        """Test list operation without superuser_full_list"""
 86        self.client.force_login(self.user)
 87        response = self.client.get(reverse("authentik_api:application-list"))
 88        self.assertJSONEqual(
 89            response.content.decode(),
 90            {
 91                "autocomplete": {},
 92                "pagination": {
 93                    "next": 0,
 94                    "previous": 0,
 95                    "count": 2,
 96                    "current": 1,
 97                    "total_pages": 1,
 98                    "start_index": 1,
 99                    "end_index": 2,
100                },
101                "results": [
102                    {
103                        "pk": str(self.allowed.pk),
104                        "name": "allowed",
105                        "slug": "allowed",
106                        "group": "",
107                        "provider": self.provider.pk,
108                        "provider_obj": {
109                            "assigned_application_name": "allowed",
110                            "assigned_application_slug": "allowed",
111                            "assigned_backchannel_application_name": None,
112                            "assigned_backchannel_application_slug": None,
113                            "authentication_flow": None,
114                            "invalidation_flow": None,
115                            "authorization_flow": str(self.provider.authorization_flow.pk),
116                            "component": "ak-provider-oauth2-form",
117                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
118                            "name": self.provider.name,
119                            "pk": self.provider.pk,
120                            "property_mappings": [],
121                            "verbose_name": "OAuth2/OpenID Provider",
122                            "verbose_name_plural": "OAuth2/OpenID Providers",
123                        },
124                        "backchannel_providers": [],
125                        "backchannel_providers_obj": [],
126                        "launch_url": f"https://goauthentik.io/{self.user.username}",
127                        "meta_launch_url": "https://goauthentik.io/%(username)s",
128                        "open_in_new_tab": True,
129                        "meta_icon": "",
130                        "meta_icon_url": None,
131                        "meta_icon_themed_urls": None,
132                        "meta_description": "",
133                        "meta_publisher": "",
134                        "policy_engine_mode": "any",
135                    },
136                ],
137            },
138        )

Test list operation without superuser_full_list

def test_list_superuser_full_list(self):
140    def test_list_superuser_full_list(self):
141        """Test list operation with superuser_full_list"""
142        self.client.force_login(self.user)
143        response = self.client.get(
144            reverse("authentik_api:application-list") + "?superuser_full_list=true"
145        )
146        self.assertJSONEqual(
147            response.content.decode(),
148            {
149                "autocomplete": {},
150                "pagination": {
151                    "next": 0,
152                    "previous": 0,
153                    "count": 2,
154                    "current": 1,
155                    "total_pages": 1,
156                    "start_index": 1,
157                    "end_index": 2,
158                },
159                "results": [
160                    {
161                        "pk": str(self.allowed.pk),
162                        "name": "allowed",
163                        "slug": "allowed",
164                        "group": "",
165                        "provider": self.provider.pk,
166                        "provider_obj": {
167                            "assigned_application_name": "allowed",
168                            "assigned_application_slug": "allowed",
169                            "assigned_backchannel_application_name": None,
170                            "assigned_backchannel_application_slug": None,
171                            "authentication_flow": None,
172                            "invalidation_flow": None,
173                            "authorization_flow": str(self.provider.authorization_flow.pk),
174                            "component": "ak-provider-oauth2-form",
175                            "meta_model_name": "authentik_providers_oauth2.oauth2provider",
176                            "name": self.provider.name,
177                            "pk": self.provider.pk,
178                            "property_mappings": [],
179                            "verbose_name": "OAuth2/OpenID Provider",
180                            "verbose_name_plural": "OAuth2/OpenID Providers",
181                        },
182                        "backchannel_providers": [],
183                        "backchannel_providers_obj": [],
184                        "launch_url": f"https://goauthentik.io/{self.user.username}",
185                        "meta_launch_url": "https://goauthentik.io/%(username)s",
186                        "open_in_new_tab": True,
187                        "meta_icon": "",
188                        "meta_icon_url": None,
189                        "meta_icon_themed_urls": None,
190                        "meta_description": "",
191                        "meta_publisher": "",
192                        "policy_engine_mode": "any",
193                    },
194                    {
195                        "launch_url": None,
196                        "meta_description": "",
197                        "meta_icon": "",
198                        "meta_icon_url": None,
199                        "meta_icon_themed_urls": None,
200                        "meta_launch_url": "",
201                        "open_in_new_tab": False,
202                        "meta_publisher": "",
203                        "group": "",
204                        "name": "denied",
205                        "pk": str(self.denied.pk),
206                        "policy_engine_mode": "any",
207                        "provider": None,
208                        "provider_obj": None,
209                        "backchannel_providers": [],
210                        "backchannel_providers_obj": [],
211                        "slug": "denied",
212                    },
213                ],
214            },
215        )

Test list operation with superuser_full_list

def test_get_provider(self):
217    def test_get_provider(self):
218        """Ensure that proxy providers (at the time of writing that is the only provider
219        that inherits from another proxy type (OAuth) instead of inheriting from the root
220        provider class) is correctly looked up and selected from the database"""
221        slug = generate_id()
222        provider = ProxyProvider.objects.create(name=generate_id())
223        Application.objects.create(
224            name=generate_id(),
225            slug=slug,
226            provider=provider,
227        )
228        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
229        self.assertEqual(
230            Application.objects.with_provider().get(slug=slug).get_provider(), provider
231        )
232
233        slug = generate_id()
234        provider = SAMLProvider.objects.create(name=generate_id())
235        Application.objects.create(
236            name=generate_id(),
237            slug=slug,
238            provider=provider,
239        )
240        self.assertEqual(Application.objects.get(slug=slug).get_provider(), provider)
241        self.assertEqual(
242            Application.objects.with_provider().get(slug=slug).get_provider(), provider
243        )

Ensure that proxy providers (at the time of writing that is the only provider that inherits from another proxy type (OAuth) instead of inheriting from the root provider class) is correctly looked up and selected from the database

def test_create_application_with_reserved_slug(self):
245    def test_create_application_with_reserved_slug(self):
246        """Test creating an application with a reserved slug"""
247        self.client.force_login(self.user)
248        response = self.client.post(
249            reverse("authentik_api:application-list"),
250            {
251                "name": "Test Application",
252                "slug": Application.reserved_slugs[0],
253            },
254        )
255        self.assertEqual(response.status_code, 400)
256        self.assertIn("slug", response.data)
257        self.assertIn("reserved", response.data["slug"][0])

Test creating an application with a reserved slug

def test_update_application_with_reserved_slug(self):
259    def test_update_application_with_reserved_slug(self):
260        """Test updating an application to use a reserved slug"""
261        self.client.force_login(self.user)
262        app = Application.objects.create(
263            name="Test Application",
264            slug="valid-slug",
265        )
266
267        response = self.client.patch(
268            reverse("authentik_api:application-detail", kwargs={"slug": app.slug}),
269            {
270                "slug": Application.reserved_slugs[0],
271            },
272        )
273        self.assertEqual(response.status_code, 400)
274        self.assertIn("slug", response.data)
275        self.assertIn("reserved", response.data["slug"][0])

Test updating an application to use a reserved slug