authentik.providers.saml.tests.test_api

SAML Provider API Tests

  1"""SAML Provider API Tests"""
  2
  3from json import loads
  4from tempfile import TemporaryFile
  5
  6from django.urls import reverse
  7from rest_framework.test import APITestCase
  8
  9from authentik.blueprints.tests import apply_blueprint
 10from authentik.core.models import Application
 11from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
 12from authentik.crypto.builder import PrivateKeyAlg
 13from authentik.flows.models import FlowDesignation
 14from authentik.lib.generators import generate_id
 15from authentik.lib.tests.utils import load_fixture
 16from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
 17
 18
 19class TestSAMLProviderAPI(APITestCase):
 20    """SAML Provider API Tests"""
 21
 22    def setUp(self) -> None:
 23        super().setUp()
 24        self.user = create_test_admin_user()
 25        self.client.force_login(self.user)
 26
 27    def test_detail(self):
 28        """Test detail"""
 29        provider = SAMLProvider.objects.create(
 30            name=generate_id(),
 31            authorization_flow=create_test_flow(),
 32        )
 33        response = self.client.get(
 34            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
 35        )
 36        self.assertEqual(200, response.status_code)
 37        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
 38        response = self.client.get(
 39            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
 40        )
 41        self.assertEqual(200, response.status_code)
 42
 43    def test_create_validate_signing_kp(self):
 44        """Test create"""
 45        cert = create_test_cert()
 46        response = self.client.post(
 47            reverse("authentik_api:samlprovider-list"),
 48            data={
 49                "name": generate_id(),
 50                "authorization_flow": create_test_flow().pk,
 51                "invalidation_flow": create_test_flow().pk,
 52                "acs_url": "http://localhost",
 53                "signing_kp": cert.pk,
 54            },
 55        )
 56        self.assertEqual(response.status_code, 400)
 57        self.assertJSONEqual(
 58            response.content,
 59            {
 60                "non_field_errors": [
 61                    (
 62                        "With a signing keypair selected, at least one "
 63                        "of 'Sign assertion' and 'Sign Response' must be selected."
 64                    )
 65                ]
 66            },
 67        )
 68        response = self.client.post(
 69            reverse("authentik_api:samlprovider-list"),
 70            data={
 71                "name": generate_id(),
 72                "authorization_flow": create_test_flow().pk,
 73                "invalidation_flow": create_test_flow().pk,
 74                "acs_url": "http://localhost",
 75                "signing_kp": cert.pk,
 76                "sign_assertion": True,
 77            },
 78        )
 79        self.assertEqual(response.status_code, 201)
 80
 81    def test_create_validate_unsupported_key_type(self):
 82        """Test validation rejects unsupported key types (Ed25519)"""
 83
 84        # Create an Ed25519 certificate
 85        ed25519_cert = create_test_cert(PrivateKeyAlg.ED25519)
 86
 87        response = self.client.post(
 88            reverse("authentik_api:samlprovider-list"),
 89            data={
 90                "name": generate_id(),
 91                "authorization_flow": create_test_flow().pk,
 92                "invalidation_flow": create_test_flow().pk,
 93                "acs_url": "http://localhost",
 94                "signing_kp": ed25519_cert.pk,
 95                "sign_assertion": True,
 96            },
 97        )
 98        self.assertEqual(response.status_code, 400)
 99        self.assertIn("signing_kp", loads(response.content))
100        self.assertJSONEqual(
101            response.content,
102            {"signing_kp": ["Only RSA, EC, and DSA key types are supported for SAML signing."]},
103        )
104
105    def test_metadata(self):
106        """Test metadata export (normal)"""
107        self.client.logout()
108        provider = SAMLProvider.objects.create(
109            name=generate_id(),
110            authorization_flow=create_test_flow(),
111        )
112        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
113        response = self.client.get(
114            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
115        )
116        self.assertEqual(200, response.status_code)
117
118    def test_metadata_download(self):
119        """Test metadata export (download)"""
120        self.client.logout()
121        provider = SAMLProvider.objects.create(
122            name=generate_id(),
123            authorization_flow=create_test_flow(),
124        )
125        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
126        response = self.client.get(
127            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
128            + "?download",
129        )
130        self.assertEqual(200, response.status_code)
131        self.assertIn("Content-Disposition", response)
132        # Test download with Accept: application/xml
133        response = self.client.get(
134            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
135            + "?download",
136            HTTP_ACCEPT="application/xml",
137        )
138        self.assertEqual(200, response.status_code)
139        self.assertIn("Content-Disposition", response)
140
141        response = self.client.get(
142            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
143            + "?download",
144            HTTP_ACCEPT="application/xml;charset=UTF-8",
145        )
146        self.assertEqual(200, response.status_code)
147        self.assertIn("Content-Disposition", response)
148
149    def test_metadata_invalid(self):
150        """Test metadata export (invalid)"""
151        self.client.logout()
152        # Provider without application
153        provider = SAMLProvider.objects.create(
154            name=generate_id(),
155            authorization_flow=create_test_flow(),
156        )
157        response = self.client.get(
158            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
159        )
160        self.assertEqual(200, response.status_code)
161        response = self.client.get(
162            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": "abc"}),
163        )
164        self.assertEqual(404, response.status_code)
165        response = self.client.get(
166            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
167            HTTP_ACCEPT="application/invalid-mime-type",
168        )
169        self.assertEqual(406, response.status_code)
170
171    def test_import_success(self):
172        """Test metadata import (success case)"""
173        name = generate_id()
174        authorization_flow = create_test_flow(FlowDesignation.AUTHORIZATION)
175        invalidation_flow = create_test_flow(FlowDesignation.INVALIDATION)
176        with TemporaryFile() as metadata:
177            metadata.write(load_fixture("fixtures/simple.xml").encode())
178            metadata.seek(0)
179            response = self.client.post(
180                reverse("authentik_api:samlprovider-import-metadata"),
181                {
182                    "file": metadata,
183                    "name": name,
184                    "authorization_flow": authorization_flow.pk,
185                    "invalidation_flow": invalidation_flow.pk,
186                },
187                format="multipart",
188            )
189        self.assertEqual(201, response.status_code)
190        body = response.json()
191        self.assertIn("pk", body)
192        self.assertEqual(body["name"], name)
193        self.assertEqual(body["authorization_flow"], str(authorization_flow.pk))
194        self.assertEqual(body["invalidation_flow"], str(invalidation_flow.pk))
195
196    def test_import_failed(self):
197        """Test metadata import (invalid xml)"""
198        with TemporaryFile() as metadata:
199            metadata.write(b"invalid")
200            metadata.seek(0)
201            response = self.client.post(
202                reverse("authentik_api:samlprovider-import-metadata"),
203                {
204                    "file": metadata,
205                    "name": generate_id(),
206                    "authorization_flow": create_test_flow().pk,
207                },
208                format="multipart",
209            )
210        self.assertEqual(400, response.status_code)
211
212    def test_import_invalid(self):
213        """Test metadata import (invalid input)"""
214        response = self.client.post(
215            reverse("authentik_api:samlprovider-import-metadata"),
216            {
217                "name": generate_id(),
218            },
219            format="multipart",
220        )
221        self.assertEqual(400, response.status_code)
222
223    @apply_blueprint("system/providers-saml.yaml")
224    def test_preview(self):
225        """Test Preview API Endpoint"""
226        provider: SAMLProvider = SAMLProvider.objects.create(
227            name=generate_id(),
228            authorization_flow=create_test_flow(),
229        )
230        provider.property_mappings.set(SAMLPropertyMapping.objects.all())
231        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
232        response = self.client.get(
233            reverse("authentik_api:samlprovider-preview-user", kwargs={"pk": provider.pk})
234        )
235        self.assertEqual(response.status_code, 200)
236        body = loads(response.content.decode())["preview"]["attributes"]
237        self.assertEqual(
238            [x for x in body if x["Name"] == "http://schemas.goauthentik.io/2021/02/saml/username"][
239                0
240            ]["Value"],
241            [self.user.username],
242        )
class TestSAMLProviderAPI(rest_framework.test.APITestCase):
 20class TestSAMLProviderAPI(APITestCase):
 21    """SAML Provider API Tests"""
 22
 23    def setUp(self) -> None:
 24        super().setUp()
 25        self.user = create_test_admin_user()
 26        self.client.force_login(self.user)
 27
 28    def test_detail(self):
 29        """Test detail"""
 30        provider = SAMLProvider.objects.create(
 31            name=generate_id(),
 32            authorization_flow=create_test_flow(),
 33        )
 34        response = self.client.get(
 35            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
 36        )
 37        self.assertEqual(200, response.status_code)
 38        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
 39        response = self.client.get(
 40            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
 41        )
 42        self.assertEqual(200, response.status_code)
 43
 44    def test_create_validate_signing_kp(self):
 45        """Test create"""
 46        cert = create_test_cert()
 47        response = self.client.post(
 48            reverse("authentik_api:samlprovider-list"),
 49            data={
 50                "name": generate_id(),
 51                "authorization_flow": create_test_flow().pk,
 52                "invalidation_flow": create_test_flow().pk,
 53                "acs_url": "http://localhost",
 54                "signing_kp": cert.pk,
 55            },
 56        )
 57        self.assertEqual(response.status_code, 400)
 58        self.assertJSONEqual(
 59            response.content,
 60            {
 61                "non_field_errors": [
 62                    (
 63                        "With a signing keypair selected, at least one "
 64                        "of 'Sign assertion' and 'Sign Response' must be selected."
 65                    )
 66                ]
 67            },
 68        )
 69        response = self.client.post(
 70            reverse("authentik_api:samlprovider-list"),
 71            data={
 72                "name": generate_id(),
 73                "authorization_flow": create_test_flow().pk,
 74                "invalidation_flow": create_test_flow().pk,
 75                "acs_url": "http://localhost",
 76                "signing_kp": cert.pk,
 77                "sign_assertion": True,
 78            },
 79        )
 80        self.assertEqual(response.status_code, 201)
 81
 82    def test_create_validate_unsupported_key_type(self):
 83        """Test validation rejects unsupported key types (Ed25519)"""
 84
 85        # Create an Ed25519 certificate
 86        ed25519_cert = create_test_cert(PrivateKeyAlg.ED25519)
 87
 88        response = self.client.post(
 89            reverse("authentik_api:samlprovider-list"),
 90            data={
 91                "name": generate_id(),
 92                "authorization_flow": create_test_flow().pk,
 93                "invalidation_flow": create_test_flow().pk,
 94                "acs_url": "http://localhost",
 95                "signing_kp": ed25519_cert.pk,
 96                "sign_assertion": True,
 97            },
 98        )
 99        self.assertEqual(response.status_code, 400)
100        self.assertIn("signing_kp", loads(response.content))
101        self.assertJSONEqual(
102            response.content,
103            {"signing_kp": ["Only RSA, EC, and DSA key types are supported for SAML signing."]},
104        )
105
106    def test_metadata(self):
107        """Test metadata export (normal)"""
108        self.client.logout()
109        provider = SAMLProvider.objects.create(
110            name=generate_id(),
111            authorization_flow=create_test_flow(),
112        )
113        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
114        response = self.client.get(
115            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
116        )
117        self.assertEqual(200, response.status_code)
118
119    def test_metadata_download(self):
120        """Test metadata export (download)"""
121        self.client.logout()
122        provider = SAMLProvider.objects.create(
123            name=generate_id(),
124            authorization_flow=create_test_flow(),
125        )
126        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
127        response = self.client.get(
128            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
129            + "?download",
130        )
131        self.assertEqual(200, response.status_code)
132        self.assertIn("Content-Disposition", response)
133        # Test download with Accept: application/xml
134        response = self.client.get(
135            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
136            + "?download",
137            HTTP_ACCEPT="application/xml",
138        )
139        self.assertEqual(200, response.status_code)
140        self.assertIn("Content-Disposition", response)
141
142        response = self.client.get(
143            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
144            + "?download",
145            HTTP_ACCEPT="application/xml;charset=UTF-8",
146        )
147        self.assertEqual(200, response.status_code)
148        self.assertIn("Content-Disposition", response)
149
150    def test_metadata_invalid(self):
151        """Test metadata export (invalid)"""
152        self.client.logout()
153        # Provider without application
154        provider = SAMLProvider.objects.create(
155            name=generate_id(),
156            authorization_flow=create_test_flow(),
157        )
158        response = self.client.get(
159            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
160        )
161        self.assertEqual(200, response.status_code)
162        response = self.client.get(
163            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": "abc"}),
164        )
165        self.assertEqual(404, response.status_code)
166        response = self.client.get(
167            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
168            HTTP_ACCEPT="application/invalid-mime-type",
169        )
170        self.assertEqual(406, response.status_code)
171
172    def test_import_success(self):
173        """Test metadata import (success case)"""
174        name = generate_id()
175        authorization_flow = create_test_flow(FlowDesignation.AUTHORIZATION)
176        invalidation_flow = create_test_flow(FlowDesignation.INVALIDATION)
177        with TemporaryFile() as metadata:
178            metadata.write(load_fixture("fixtures/simple.xml").encode())
179            metadata.seek(0)
180            response = self.client.post(
181                reverse("authentik_api:samlprovider-import-metadata"),
182                {
183                    "file": metadata,
184                    "name": name,
185                    "authorization_flow": authorization_flow.pk,
186                    "invalidation_flow": invalidation_flow.pk,
187                },
188                format="multipart",
189            )
190        self.assertEqual(201, response.status_code)
191        body = response.json()
192        self.assertIn("pk", body)
193        self.assertEqual(body["name"], name)
194        self.assertEqual(body["authorization_flow"], str(authorization_flow.pk))
195        self.assertEqual(body["invalidation_flow"], str(invalidation_flow.pk))
196
197    def test_import_failed(self):
198        """Test metadata import (invalid xml)"""
199        with TemporaryFile() as metadata:
200            metadata.write(b"invalid")
201            metadata.seek(0)
202            response = self.client.post(
203                reverse("authentik_api:samlprovider-import-metadata"),
204                {
205                    "file": metadata,
206                    "name": generate_id(),
207                    "authorization_flow": create_test_flow().pk,
208                },
209                format="multipart",
210            )
211        self.assertEqual(400, response.status_code)
212
213    def test_import_invalid(self):
214        """Test metadata import (invalid input)"""
215        response = self.client.post(
216            reverse("authentik_api:samlprovider-import-metadata"),
217            {
218                "name": generate_id(),
219            },
220            format="multipart",
221        )
222        self.assertEqual(400, response.status_code)
223
224    @apply_blueprint("system/providers-saml.yaml")
225    def test_preview(self):
226        """Test Preview API Endpoint"""
227        provider: SAMLProvider = SAMLProvider.objects.create(
228            name=generate_id(),
229            authorization_flow=create_test_flow(),
230        )
231        provider.property_mappings.set(SAMLPropertyMapping.objects.all())
232        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
233        response = self.client.get(
234            reverse("authentik_api:samlprovider-preview-user", kwargs={"pk": provider.pk})
235        )
236        self.assertEqual(response.status_code, 200)
237        body = loads(response.content.decode())["preview"]["attributes"]
238        self.assertEqual(
239            [x for x in body if x["Name"] == "http://schemas.goauthentik.io/2021/02/saml/username"][
240                0
241            ]["Value"],
242            [self.user.username],
243        )

SAML Provider API Tests

def setUp(self) -> None:
23    def setUp(self) -> None:
24        super().setUp()
25        self.user = create_test_admin_user()
26        self.client.force_login(self.user)

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

def test_detail(self):
28    def test_detail(self):
29        """Test detail"""
30        provider = SAMLProvider.objects.create(
31            name=generate_id(),
32            authorization_flow=create_test_flow(),
33        )
34        response = self.client.get(
35            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
36        )
37        self.assertEqual(200, response.status_code)
38        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
39        response = self.client.get(
40            reverse("authentik_api:samlprovider-detail", kwargs={"pk": provider.pk}),
41        )
42        self.assertEqual(200, response.status_code)

Test detail

def test_create_validate_signing_kp(self):
44    def test_create_validate_signing_kp(self):
45        """Test create"""
46        cert = create_test_cert()
47        response = self.client.post(
48            reverse("authentik_api:samlprovider-list"),
49            data={
50                "name": generate_id(),
51                "authorization_flow": create_test_flow().pk,
52                "invalidation_flow": create_test_flow().pk,
53                "acs_url": "http://localhost",
54                "signing_kp": cert.pk,
55            },
56        )
57        self.assertEqual(response.status_code, 400)
58        self.assertJSONEqual(
59            response.content,
60            {
61                "non_field_errors": [
62                    (
63                        "With a signing keypair selected, at least one "
64                        "of 'Sign assertion' and 'Sign Response' must be selected."
65                    )
66                ]
67            },
68        )
69        response = self.client.post(
70            reverse("authentik_api:samlprovider-list"),
71            data={
72                "name": generate_id(),
73                "authorization_flow": create_test_flow().pk,
74                "invalidation_flow": create_test_flow().pk,
75                "acs_url": "http://localhost",
76                "signing_kp": cert.pk,
77                "sign_assertion": True,
78            },
79        )
80        self.assertEqual(response.status_code, 201)

Test create

def test_create_validate_unsupported_key_type(self):
 82    def test_create_validate_unsupported_key_type(self):
 83        """Test validation rejects unsupported key types (Ed25519)"""
 84
 85        # Create an Ed25519 certificate
 86        ed25519_cert = create_test_cert(PrivateKeyAlg.ED25519)
 87
 88        response = self.client.post(
 89            reverse("authentik_api:samlprovider-list"),
 90            data={
 91                "name": generate_id(),
 92                "authorization_flow": create_test_flow().pk,
 93                "invalidation_flow": create_test_flow().pk,
 94                "acs_url": "http://localhost",
 95                "signing_kp": ed25519_cert.pk,
 96                "sign_assertion": True,
 97            },
 98        )
 99        self.assertEqual(response.status_code, 400)
100        self.assertIn("signing_kp", loads(response.content))
101        self.assertJSONEqual(
102            response.content,
103            {"signing_kp": ["Only RSA, EC, and DSA key types are supported for SAML signing."]},
104        )

Test validation rejects unsupported key types (Ed25519)

def test_metadata(self):
106    def test_metadata(self):
107        """Test metadata export (normal)"""
108        self.client.logout()
109        provider = SAMLProvider.objects.create(
110            name=generate_id(),
111            authorization_flow=create_test_flow(),
112        )
113        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
114        response = self.client.get(
115            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
116        )
117        self.assertEqual(200, response.status_code)

Test metadata export (normal)

def test_metadata_download(self):
119    def test_metadata_download(self):
120        """Test metadata export (download)"""
121        self.client.logout()
122        provider = SAMLProvider.objects.create(
123            name=generate_id(),
124            authorization_flow=create_test_flow(),
125        )
126        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
127        response = self.client.get(
128            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
129            + "?download",
130        )
131        self.assertEqual(200, response.status_code)
132        self.assertIn("Content-Disposition", response)
133        # Test download with Accept: application/xml
134        response = self.client.get(
135            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
136            + "?download",
137            HTTP_ACCEPT="application/xml",
138        )
139        self.assertEqual(200, response.status_code)
140        self.assertIn("Content-Disposition", response)
141
142        response = self.client.get(
143            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk})
144            + "?download",
145            HTTP_ACCEPT="application/xml;charset=UTF-8",
146        )
147        self.assertEqual(200, response.status_code)
148        self.assertIn("Content-Disposition", response)

Test metadata export (download)

def test_metadata_invalid(self):
150    def test_metadata_invalid(self):
151        """Test metadata export (invalid)"""
152        self.client.logout()
153        # Provider without application
154        provider = SAMLProvider.objects.create(
155            name=generate_id(),
156            authorization_flow=create_test_flow(),
157        )
158        response = self.client.get(
159            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
160        )
161        self.assertEqual(200, response.status_code)
162        response = self.client.get(
163            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": "abc"}),
164        )
165        self.assertEqual(404, response.status_code)
166        response = self.client.get(
167            reverse("authentik_api:samlprovider-metadata", kwargs={"pk": provider.pk}),
168            HTTP_ACCEPT="application/invalid-mime-type",
169        )
170        self.assertEqual(406, response.status_code)

Test metadata export (invalid)

def test_import_success(self):
172    def test_import_success(self):
173        """Test metadata import (success case)"""
174        name = generate_id()
175        authorization_flow = create_test_flow(FlowDesignation.AUTHORIZATION)
176        invalidation_flow = create_test_flow(FlowDesignation.INVALIDATION)
177        with TemporaryFile() as metadata:
178            metadata.write(load_fixture("fixtures/simple.xml").encode())
179            metadata.seek(0)
180            response = self.client.post(
181                reverse("authentik_api:samlprovider-import-metadata"),
182                {
183                    "file": metadata,
184                    "name": name,
185                    "authorization_flow": authorization_flow.pk,
186                    "invalidation_flow": invalidation_flow.pk,
187                },
188                format="multipart",
189            )
190        self.assertEqual(201, response.status_code)
191        body = response.json()
192        self.assertIn("pk", body)
193        self.assertEqual(body["name"], name)
194        self.assertEqual(body["authorization_flow"], str(authorization_flow.pk))
195        self.assertEqual(body["invalidation_flow"], str(invalidation_flow.pk))

Test metadata import (success case)

def test_import_failed(self):
197    def test_import_failed(self):
198        """Test metadata import (invalid xml)"""
199        with TemporaryFile() as metadata:
200            metadata.write(b"invalid")
201            metadata.seek(0)
202            response = self.client.post(
203                reverse("authentik_api:samlprovider-import-metadata"),
204                {
205                    "file": metadata,
206                    "name": generate_id(),
207                    "authorization_flow": create_test_flow().pk,
208                },
209                format="multipart",
210            )
211        self.assertEqual(400, response.status_code)

Test metadata import (invalid xml)

def test_import_invalid(self):
213    def test_import_invalid(self):
214        """Test metadata import (invalid input)"""
215        response = self.client.post(
216            reverse("authentik_api:samlprovider-import-metadata"),
217            {
218                "name": generate_id(),
219            },
220            format="multipart",
221        )
222        self.assertEqual(400, response.status_code)

Test metadata import (invalid input)

@apply_blueprint('system/providers-saml.yaml')
def test_preview(self):
224    @apply_blueprint("system/providers-saml.yaml")
225    def test_preview(self):
226        """Test Preview API Endpoint"""
227        provider: SAMLProvider = SAMLProvider.objects.create(
228            name=generate_id(),
229            authorization_flow=create_test_flow(),
230        )
231        provider.property_mappings.set(SAMLPropertyMapping.objects.all())
232        Application.objects.create(name=generate_id(), provider=provider, slug=generate_id())
233        response = self.client.get(
234            reverse("authentik_api:samlprovider-preview-user", kwargs={"pk": provider.pk})
235        )
236        self.assertEqual(response.status_code, 200)
237        body = loads(response.content.decode())["preview"]["attributes"]
238        self.assertEqual(
239            [x for x in body if x["Name"] == "http://schemas.goauthentik.io/2021/02/saml/username"][
240                0
241            ]["Value"],
242            [self.user.username],
243        )

Test Preview API Endpoint