authentik.providers.saml.tests.test_models_session

Test SAMLSession Model

  1"""Test SAMLSession Model"""
  2
  3from datetime import timedelta
  4
  5from django.db import IntegrityError
  6from django.test import TestCase
  7from django.utils import timezone
  8
  9from authentik.common.saml.constants import (
 10    SAML_NAME_ID_FORMAT_EMAIL,
 11)
 12from authentik.core.models import AuthenticatedSession, Session, User
 13from authentik.core.tests.utils import create_test_flow
 14from authentik.lib.generators import generate_id
 15from authentik.providers.saml.api.sessions import SAMLSessionSerializer
 16from authentik.providers.saml.models import SAMLProvider, SAMLSession
 17
 18
 19class TestSAMLSessionModel(TestCase):
 20    """Test SAMLSession model functionality"""
 21
 22    def setUp(self):
 23        """Set up test fixtures"""
 24        self.user = User.objects.create_user(
 25            username="testuser",
 26            email="test@example.com",
 27        )
 28        self.flow = create_test_flow()
 29
 30        # Create a provider
 31        self.provider = SAMLProvider.objects.create(
 32            name="test-provider",
 33            authorization_flow=self.flow,
 34            acs_url="https://sp.example.com/acs",
 35            issuer="https://idp.example.com",
 36        )
 37
 38        # Create another provider for testing
 39        self.provider2 = SAMLProvider.objects.create(
 40            name="test-provider-2",
 41            authorization_flow=self.flow,
 42            acs_url="https://sp2.example.com/acs",
 43            issuer="https://idp2.example.com",
 44        )
 45
 46        # Create a session first (using authentik's custom Session model)
 47        self.django_session = Session.objects.create(
 48            session_key=generate_id(),
 49            last_ip="127.0.0.1",
 50        )
 51
 52        # Create an authenticated session
 53        self.auth_session = AuthenticatedSession.objects.create(
 54            session=self.django_session,
 55            user=self.user,
 56        )
 57
 58        # Session data
 59        self.session_index = generate_id()
 60        self.name_id = "test@example.com"
 61        self.name_id_format = SAML_NAME_ID_FORMAT_EMAIL
 62        self.expires = timezone.now() + timedelta(hours=8)
 63
 64    def test_session_creation(self):
 65        """Test creating a SAML session"""
 66        saml_session = SAMLSession.objects.create(
 67            provider=self.provider,
 68            user=self.user,
 69            session=self.auth_session,
 70            session_index=self.session_index,
 71            name_id=self.name_id,
 72            name_id_format=self.name_id_format,
 73            expires=self.expires,
 74            expiring=True,
 75        )
 76
 77        # Verify the session was created
 78        self.assertIsNotNone(saml_session.pk)
 79        self.assertEqual(saml_session.provider, self.provider)
 80        self.assertEqual(saml_session.user, self.user)
 81        self.assertEqual(saml_session.session, self.auth_session)
 82        self.assertEqual(saml_session.session_index, self.session_index)
 83        self.assertEqual(saml_session.name_id, self.name_id)
 84        self.assertEqual(saml_session.name_id_format, self.name_id_format)
 85        self.assertIsNotNone(saml_session.created)
 86
 87        # Test string representation
 88        expected_str = f"SAML Session for provider {self.provider.pk} and user {self.user.pk}"
 89        self.assertEqual(str(saml_session), expected_str)
 90
 91    def test_unique_constraint_session_index_provider(self):
 92        """Test that session_index must be unique per provider"""
 93        # Create first session
 94        SAMLSession.objects.create(
 95            provider=self.provider,
 96            user=self.user,
 97            session=self.auth_session,
 98            session_index=self.session_index,
 99            name_id=self.name_id,
100            name_id_format=self.name_id_format,
101            expires=self.expires,
102            expiring=True,
103        )
104
105        # Try to create another session with same session_index and provider
106        with self.assertRaises(IntegrityError):
107            SAMLSession.objects.create(
108                provider=self.provider,
109                user=self.user,
110                session=self.auth_session,
111                session_index=self.session_index,  # Same session_index
112                name_id="different@example.com",
113                name_id_format=self.name_id_format,
114                expires=self.expires,
115                expiring=True,
116            )
117
118    def test_cascade_deletion_user(self):
119        """Test that deleting a user deletes associated SAML sessions"""
120        # Create SAML session
121        saml_session = SAMLSession.objects.create(
122            provider=self.provider,
123            user=self.user,
124            session=self.auth_session,
125            session_index=self.session_index,
126            name_id=self.name_id,
127            name_id_format=self.name_id_format,
128            expires=self.expires,
129            expiring=True,
130        )
131
132        # Verify session exists
133        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
134
135        # Delete the user
136        self.user.delete()
137
138        # Verify SAML session was deleted
139        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
140
141    def test_cascade_deletion_provider(self):
142        """Test that deleting a provider deletes associated SAML sessions"""
143        # Create SAML session
144        saml_session = SAMLSession.objects.create(
145            provider=self.provider,
146            user=self.user,
147            session=self.auth_session,
148            session_index=self.session_index,
149            name_id=self.name_id,
150            name_id_format=self.name_id_format,
151            expires=self.expires,
152            expiring=True,
153        )
154
155        # Verify session exists
156        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
157
158        # Delete the provider
159        self.provider.delete()
160
161        # Verify SAML session was deleted
162        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
163
164    def test_cascade_deletion_authenticated_session(self):
165        """Test that deleting an AuthenticatedSession deletes associated SAML sessions"""
166        # Create SAML session
167        saml_session = SAMLSession.objects.create(
168            provider=self.provider,
169            user=self.user,
170            session=self.auth_session,
171            session_index=self.session_index,
172            name_id=self.name_id,
173            name_id_format=self.name_id_format,
174            expires=self.expires,
175            expiring=True,
176        )
177
178        # Verify session exists
179        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
180
181        # Delete the authenticated session
182        self.auth_session.delete()
183
184        # Verify SAML session was deleted
185        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
186
187    def test_multiple_sessions_per_user(self):
188        """Test that a user can have multiple SAML sessions with different providers"""
189        # Create first session
190        session1 = SAMLSession.objects.create(
191            provider=self.provider,
192            user=self.user,
193            session=self.auth_session,
194            session_index=generate_id(),
195            name_id=self.name_id,
196            name_id_format=self.name_id_format,
197            expires=self.expires,
198            expiring=True,
199        )
200
201        # Create second session with different provider
202        session2 = SAMLSession.objects.create(
203            provider=self.provider2,
204            user=self.user,
205            session=self.auth_session,
206            session_index=generate_id(),
207            name_id=self.name_id,
208            name_id_format=self.name_id_format,
209            expires=self.expires,
210            expiring=True,
211        )
212
213        # Verify both sessions exist
214        user_sessions = SAMLSession.objects.filter(user=self.user)
215        self.assertEqual(user_sessions.count(), 2)
216        self.assertIn(session1, user_sessions)
217        self.assertIn(session2, user_sessions)
218
219    def test_session_expiry_tracking(self):
220        """Test that session expiry time is properly stored"""
221        # Create session with specific expiry
222        future_time = timezone.now() + timedelta(hours=24)
223        saml_session = SAMLSession.objects.create(
224            provider=self.provider,
225            user=self.user,
226            session=self.auth_session,
227            session_index=self.session_index,
228            name_id=self.name_id,
229            name_id_format=self.name_id_format,
230            expires=future_time,
231            expiring=True,
232        )
233
234        # Verify expiry time
235        self.assertEqual(saml_session.expires, future_time)
236
237        # Check if session is expired (ExpiringModel behavior)
238        self.assertFalse(saml_session.is_expired)
239
240        # Create an expired session
241        past_time = timezone.now() - timedelta(hours=1)
242        expired_session = SAMLSession.objects.create(
243            provider=self.provider2,
244            user=self.user,
245            session=self.auth_session,
246            session_index=generate_id(),
247            name_id=self.name_id,
248            name_id_format=self.name_id_format,
249            expires=past_time,
250            expiring=True,
251        )
252
253        # Check if marked as expired
254        self.assertTrue(expired_session.is_expired)
255
256    def test_name_id_format_optional(self):
257        """Test that name_id_format is optional (can be blank)"""
258        # Create session without name_id_format
259        saml_session = SAMLSession.objects.create(
260            provider=self.provider,
261            user=self.user,
262            session=self.auth_session,
263            session_index=self.session_index,
264            name_id=self.name_id,
265            name_id_format="",  # Blank format
266            expires=self.expires,
267            expiring=True,
268        )
269
270        # Verify it was created successfully
271        self.assertIsNotNone(saml_session.pk)
272        self.assertEqual(saml_session.name_id_format, "")
273
274    def test_query_sessions_by_provider(self):
275        """Test querying sessions by provider"""
276        # Create sessions for different providers
277        session1 = SAMLSession.objects.create(
278            provider=self.provider,
279            user=self.user,
280            session=self.auth_session,
281            session_index=generate_id(),
282            name_id=self.name_id,
283            name_id_format=self.name_id_format,
284            expires=self.expires,
285            expiring=True,
286        )
287
288        session2 = SAMLSession.objects.create(
289            provider=self.provider2,
290            user=self.user,
291            session=self.auth_session,
292            session_index=generate_id(),
293            name_id=self.name_id,
294            name_id_format=self.name_id_format,
295            expires=self.expires,
296            expiring=True,
297        )
298
299        # Query by provider
300        provider1_sessions = SAMLSession.objects.filter(provider=self.provider)
301        self.assertEqual(provider1_sessions.count(), 1)
302        self.assertEqual(provider1_sessions.first(), session1)
303
304        provider2_sessions = SAMLSession.objects.filter(provider=self.provider2)
305        self.assertEqual(provider2_sessions.count(), 1)
306        self.assertEqual(provider2_sessions.first(), session2)
307
308    def test_serializer_property(self):
309        """Test that the serializer property returns the correct serializer"""
310        saml_session = SAMLSession.objects.create(
311            provider=self.provider,
312            user=self.user,
313            session=self.auth_session,
314            session_index=self.session_index,
315            name_id=self.name_id,
316            name_id_format=self.name_id_format,
317            expires=self.expires,
318            expiring=True,
319        )
320
321        # Check serializer property
322        self.assertEqual(saml_session.serializer, SAMLSessionSerializer)
323
324    def test_bulk_delete_sessions_for_user(self):
325        """Test bulk deletion of all SAML sessions for a user"""
326        # Create multiple sessions
327        for i in range(3):
328            SAMLSession.objects.create(
329                provider=self.provider if i % 2 == 0 else self.provider2,
330                user=self.user,
331                session=self.auth_session,
332                session_index=generate_id(),
333                name_id=self.name_id,
334                name_id_format=self.name_id_format,
335                expires=self.expires,
336                expiring=True,
337            )
338
339        # Verify sessions exist
340        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 3)
341
342        # Delete all sessions for the user
343        deleted_count, _ = SAMLSession.objects.filter(user=self.user).delete()
344
345        # Verify all were deleted
346        self.assertEqual(deleted_count, 3)
347        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 0)
class TestSAMLSessionModel(django.test.testcases.TestCase):
 20class TestSAMLSessionModel(TestCase):
 21    """Test SAMLSession model functionality"""
 22
 23    def setUp(self):
 24        """Set up test fixtures"""
 25        self.user = User.objects.create_user(
 26            username="testuser",
 27            email="test@example.com",
 28        )
 29        self.flow = create_test_flow()
 30
 31        # Create a provider
 32        self.provider = SAMLProvider.objects.create(
 33            name="test-provider",
 34            authorization_flow=self.flow,
 35            acs_url="https://sp.example.com/acs",
 36            issuer="https://idp.example.com",
 37        )
 38
 39        # Create another provider for testing
 40        self.provider2 = SAMLProvider.objects.create(
 41            name="test-provider-2",
 42            authorization_flow=self.flow,
 43            acs_url="https://sp2.example.com/acs",
 44            issuer="https://idp2.example.com",
 45        )
 46
 47        # Create a session first (using authentik's custom Session model)
 48        self.django_session = Session.objects.create(
 49            session_key=generate_id(),
 50            last_ip="127.0.0.1",
 51        )
 52
 53        # Create an authenticated session
 54        self.auth_session = AuthenticatedSession.objects.create(
 55            session=self.django_session,
 56            user=self.user,
 57        )
 58
 59        # Session data
 60        self.session_index = generate_id()
 61        self.name_id = "test@example.com"
 62        self.name_id_format = SAML_NAME_ID_FORMAT_EMAIL
 63        self.expires = timezone.now() + timedelta(hours=8)
 64
 65    def test_session_creation(self):
 66        """Test creating a SAML session"""
 67        saml_session = SAMLSession.objects.create(
 68            provider=self.provider,
 69            user=self.user,
 70            session=self.auth_session,
 71            session_index=self.session_index,
 72            name_id=self.name_id,
 73            name_id_format=self.name_id_format,
 74            expires=self.expires,
 75            expiring=True,
 76        )
 77
 78        # Verify the session was created
 79        self.assertIsNotNone(saml_session.pk)
 80        self.assertEqual(saml_session.provider, self.provider)
 81        self.assertEqual(saml_session.user, self.user)
 82        self.assertEqual(saml_session.session, self.auth_session)
 83        self.assertEqual(saml_session.session_index, self.session_index)
 84        self.assertEqual(saml_session.name_id, self.name_id)
 85        self.assertEqual(saml_session.name_id_format, self.name_id_format)
 86        self.assertIsNotNone(saml_session.created)
 87
 88        # Test string representation
 89        expected_str = f"SAML Session for provider {self.provider.pk} and user {self.user.pk}"
 90        self.assertEqual(str(saml_session), expected_str)
 91
 92    def test_unique_constraint_session_index_provider(self):
 93        """Test that session_index must be unique per provider"""
 94        # Create first session
 95        SAMLSession.objects.create(
 96            provider=self.provider,
 97            user=self.user,
 98            session=self.auth_session,
 99            session_index=self.session_index,
100            name_id=self.name_id,
101            name_id_format=self.name_id_format,
102            expires=self.expires,
103            expiring=True,
104        )
105
106        # Try to create another session with same session_index and provider
107        with self.assertRaises(IntegrityError):
108            SAMLSession.objects.create(
109                provider=self.provider,
110                user=self.user,
111                session=self.auth_session,
112                session_index=self.session_index,  # Same session_index
113                name_id="different@example.com",
114                name_id_format=self.name_id_format,
115                expires=self.expires,
116                expiring=True,
117            )
118
119    def test_cascade_deletion_user(self):
120        """Test that deleting a user deletes associated SAML sessions"""
121        # Create SAML session
122        saml_session = SAMLSession.objects.create(
123            provider=self.provider,
124            user=self.user,
125            session=self.auth_session,
126            session_index=self.session_index,
127            name_id=self.name_id,
128            name_id_format=self.name_id_format,
129            expires=self.expires,
130            expiring=True,
131        )
132
133        # Verify session exists
134        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
135
136        # Delete the user
137        self.user.delete()
138
139        # Verify SAML session was deleted
140        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
141
142    def test_cascade_deletion_provider(self):
143        """Test that deleting a provider deletes associated SAML sessions"""
144        # Create SAML session
145        saml_session = SAMLSession.objects.create(
146            provider=self.provider,
147            user=self.user,
148            session=self.auth_session,
149            session_index=self.session_index,
150            name_id=self.name_id,
151            name_id_format=self.name_id_format,
152            expires=self.expires,
153            expiring=True,
154        )
155
156        # Verify session exists
157        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
158
159        # Delete the provider
160        self.provider.delete()
161
162        # Verify SAML session was deleted
163        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
164
165    def test_cascade_deletion_authenticated_session(self):
166        """Test that deleting an AuthenticatedSession deletes associated SAML sessions"""
167        # Create SAML session
168        saml_session = SAMLSession.objects.create(
169            provider=self.provider,
170            user=self.user,
171            session=self.auth_session,
172            session_index=self.session_index,
173            name_id=self.name_id,
174            name_id_format=self.name_id_format,
175            expires=self.expires,
176            expiring=True,
177        )
178
179        # Verify session exists
180        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
181
182        # Delete the authenticated session
183        self.auth_session.delete()
184
185        # Verify SAML session was deleted
186        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())
187
188    def test_multiple_sessions_per_user(self):
189        """Test that a user can have multiple SAML sessions with different providers"""
190        # Create first session
191        session1 = SAMLSession.objects.create(
192            provider=self.provider,
193            user=self.user,
194            session=self.auth_session,
195            session_index=generate_id(),
196            name_id=self.name_id,
197            name_id_format=self.name_id_format,
198            expires=self.expires,
199            expiring=True,
200        )
201
202        # Create second session with different provider
203        session2 = SAMLSession.objects.create(
204            provider=self.provider2,
205            user=self.user,
206            session=self.auth_session,
207            session_index=generate_id(),
208            name_id=self.name_id,
209            name_id_format=self.name_id_format,
210            expires=self.expires,
211            expiring=True,
212        )
213
214        # Verify both sessions exist
215        user_sessions = SAMLSession.objects.filter(user=self.user)
216        self.assertEqual(user_sessions.count(), 2)
217        self.assertIn(session1, user_sessions)
218        self.assertIn(session2, user_sessions)
219
220    def test_session_expiry_tracking(self):
221        """Test that session expiry time is properly stored"""
222        # Create session with specific expiry
223        future_time = timezone.now() + timedelta(hours=24)
224        saml_session = SAMLSession.objects.create(
225            provider=self.provider,
226            user=self.user,
227            session=self.auth_session,
228            session_index=self.session_index,
229            name_id=self.name_id,
230            name_id_format=self.name_id_format,
231            expires=future_time,
232            expiring=True,
233        )
234
235        # Verify expiry time
236        self.assertEqual(saml_session.expires, future_time)
237
238        # Check if session is expired (ExpiringModel behavior)
239        self.assertFalse(saml_session.is_expired)
240
241        # Create an expired session
242        past_time = timezone.now() - timedelta(hours=1)
243        expired_session = SAMLSession.objects.create(
244            provider=self.provider2,
245            user=self.user,
246            session=self.auth_session,
247            session_index=generate_id(),
248            name_id=self.name_id,
249            name_id_format=self.name_id_format,
250            expires=past_time,
251            expiring=True,
252        )
253
254        # Check if marked as expired
255        self.assertTrue(expired_session.is_expired)
256
257    def test_name_id_format_optional(self):
258        """Test that name_id_format is optional (can be blank)"""
259        # Create session without name_id_format
260        saml_session = SAMLSession.objects.create(
261            provider=self.provider,
262            user=self.user,
263            session=self.auth_session,
264            session_index=self.session_index,
265            name_id=self.name_id,
266            name_id_format="",  # Blank format
267            expires=self.expires,
268            expiring=True,
269        )
270
271        # Verify it was created successfully
272        self.assertIsNotNone(saml_session.pk)
273        self.assertEqual(saml_session.name_id_format, "")
274
275    def test_query_sessions_by_provider(self):
276        """Test querying sessions by provider"""
277        # Create sessions for different providers
278        session1 = SAMLSession.objects.create(
279            provider=self.provider,
280            user=self.user,
281            session=self.auth_session,
282            session_index=generate_id(),
283            name_id=self.name_id,
284            name_id_format=self.name_id_format,
285            expires=self.expires,
286            expiring=True,
287        )
288
289        session2 = SAMLSession.objects.create(
290            provider=self.provider2,
291            user=self.user,
292            session=self.auth_session,
293            session_index=generate_id(),
294            name_id=self.name_id,
295            name_id_format=self.name_id_format,
296            expires=self.expires,
297            expiring=True,
298        )
299
300        # Query by provider
301        provider1_sessions = SAMLSession.objects.filter(provider=self.provider)
302        self.assertEqual(provider1_sessions.count(), 1)
303        self.assertEqual(provider1_sessions.first(), session1)
304
305        provider2_sessions = SAMLSession.objects.filter(provider=self.provider2)
306        self.assertEqual(provider2_sessions.count(), 1)
307        self.assertEqual(provider2_sessions.first(), session2)
308
309    def test_serializer_property(self):
310        """Test that the serializer property returns the correct serializer"""
311        saml_session = SAMLSession.objects.create(
312            provider=self.provider,
313            user=self.user,
314            session=self.auth_session,
315            session_index=self.session_index,
316            name_id=self.name_id,
317            name_id_format=self.name_id_format,
318            expires=self.expires,
319            expiring=True,
320        )
321
322        # Check serializer property
323        self.assertEqual(saml_session.serializer, SAMLSessionSerializer)
324
325    def test_bulk_delete_sessions_for_user(self):
326        """Test bulk deletion of all SAML sessions for a user"""
327        # Create multiple sessions
328        for i in range(3):
329            SAMLSession.objects.create(
330                provider=self.provider if i % 2 == 0 else self.provider2,
331                user=self.user,
332                session=self.auth_session,
333                session_index=generate_id(),
334                name_id=self.name_id,
335                name_id_format=self.name_id_format,
336                expires=self.expires,
337                expiring=True,
338            )
339
340        # Verify sessions exist
341        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 3)
342
343        # Delete all sessions for the user
344        deleted_count, _ = SAMLSession.objects.filter(user=self.user).delete()
345
346        # Verify all were deleted
347        self.assertEqual(deleted_count, 3)
348        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 0)

Test SAMLSession model functionality

def setUp(self):
23    def setUp(self):
24        """Set up test fixtures"""
25        self.user = User.objects.create_user(
26            username="testuser",
27            email="test@example.com",
28        )
29        self.flow = create_test_flow()
30
31        # Create a provider
32        self.provider = SAMLProvider.objects.create(
33            name="test-provider",
34            authorization_flow=self.flow,
35            acs_url="https://sp.example.com/acs",
36            issuer="https://idp.example.com",
37        )
38
39        # Create another provider for testing
40        self.provider2 = SAMLProvider.objects.create(
41            name="test-provider-2",
42            authorization_flow=self.flow,
43            acs_url="https://sp2.example.com/acs",
44            issuer="https://idp2.example.com",
45        )
46
47        # Create a session first (using authentik's custom Session model)
48        self.django_session = Session.objects.create(
49            session_key=generate_id(),
50            last_ip="127.0.0.1",
51        )
52
53        # Create an authenticated session
54        self.auth_session = AuthenticatedSession.objects.create(
55            session=self.django_session,
56            user=self.user,
57        )
58
59        # Session data
60        self.session_index = generate_id()
61        self.name_id = "test@example.com"
62        self.name_id_format = SAML_NAME_ID_FORMAT_EMAIL
63        self.expires = timezone.now() + timedelta(hours=8)

Set up test fixtures

def test_session_creation(self):
65    def test_session_creation(self):
66        """Test creating a SAML session"""
67        saml_session = SAMLSession.objects.create(
68            provider=self.provider,
69            user=self.user,
70            session=self.auth_session,
71            session_index=self.session_index,
72            name_id=self.name_id,
73            name_id_format=self.name_id_format,
74            expires=self.expires,
75            expiring=True,
76        )
77
78        # Verify the session was created
79        self.assertIsNotNone(saml_session.pk)
80        self.assertEqual(saml_session.provider, self.provider)
81        self.assertEqual(saml_session.user, self.user)
82        self.assertEqual(saml_session.session, self.auth_session)
83        self.assertEqual(saml_session.session_index, self.session_index)
84        self.assertEqual(saml_session.name_id, self.name_id)
85        self.assertEqual(saml_session.name_id_format, self.name_id_format)
86        self.assertIsNotNone(saml_session.created)
87
88        # Test string representation
89        expected_str = f"SAML Session for provider {self.provider.pk} and user {self.user.pk}"
90        self.assertEqual(str(saml_session), expected_str)

Test creating a SAML session

def test_unique_constraint_session_index_provider(self):
 92    def test_unique_constraint_session_index_provider(self):
 93        """Test that session_index must be unique per provider"""
 94        # Create first session
 95        SAMLSession.objects.create(
 96            provider=self.provider,
 97            user=self.user,
 98            session=self.auth_session,
 99            session_index=self.session_index,
100            name_id=self.name_id,
101            name_id_format=self.name_id_format,
102            expires=self.expires,
103            expiring=True,
104        )
105
106        # Try to create another session with same session_index and provider
107        with self.assertRaises(IntegrityError):
108            SAMLSession.objects.create(
109                provider=self.provider,
110                user=self.user,
111                session=self.auth_session,
112                session_index=self.session_index,  # Same session_index
113                name_id="different@example.com",
114                name_id_format=self.name_id_format,
115                expires=self.expires,
116                expiring=True,
117            )

Test that session_index must be unique per provider

def test_cascade_deletion_user(self):
119    def test_cascade_deletion_user(self):
120        """Test that deleting a user deletes associated SAML sessions"""
121        # Create SAML session
122        saml_session = SAMLSession.objects.create(
123            provider=self.provider,
124            user=self.user,
125            session=self.auth_session,
126            session_index=self.session_index,
127            name_id=self.name_id,
128            name_id_format=self.name_id_format,
129            expires=self.expires,
130            expiring=True,
131        )
132
133        # Verify session exists
134        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
135
136        # Delete the user
137        self.user.delete()
138
139        # Verify SAML session was deleted
140        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())

Test that deleting a user deletes associated SAML sessions

def test_cascade_deletion_provider(self):
142    def test_cascade_deletion_provider(self):
143        """Test that deleting a provider deletes associated SAML sessions"""
144        # Create SAML session
145        saml_session = SAMLSession.objects.create(
146            provider=self.provider,
147            user=self.user,
148            session=self.auth_session,
149            session_index=self.session_index,
150            name_id=self.name_id,
151            name_id_format=self.name_id_format,
152            expires=self.expires,
153            expiring=True,
154        )
155
156        # Verify session exists
157        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
158
159        # Delete the provider
160        self.provider.delete()
161
162        # Verify SAML session was deleted
163        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())

Test that deleting a provider deletes associated SAML sessions

def test_cascade_deletion_authenticated_session(self):
165    def test_cascade_deletion_authenticated_session(self):
166        """Test that deleting an AuthenticatedSession deletes associated SAML sessions"""
167        # Create SAML session
168        saml_session = SAMLSession.objects.create(
169            provider=self.provider,
170            user=self.user,
171            session=self.auth_session,
172            session_index=self.session_index,
173            name_id=self.name_id,
174            name_id_format=self.name_id_format,
175            expires=self.expires,
176            expiring=True,
177        )
178
179        # Verify session exists
180        self.assertTrue(SAMLSession.objects.filter(pk=saml_session.pk).exists())
181
182        # Delete the authenticated session
183        self.auth_session.delete()
184
185        # Verify SAML session was deleted
186        self.assertFalse(SAMLSession.objects.filter(pk=saml_session.pk).exists())

Test that deleting an AuthenticatedSession deletes associated SAML sessions

def test_multiple_sessions_per_user(self):
188    def test_multiple_sessions_per_user(self):
189        """Test that a user can have multiple SAML sessions with different providers"""
190        # Create first session
191        session1 = SAMLSession.objects.create(
192            provider=self.provider,
193            user=self.user,
194            session=self.auth_session,
195            session_index=generate_id(),
196            name_id=self.name_id,
197            name_id_format=self.name_id_format,
198            expires=self.expires,
199            expiring=True,
200        )
201
202        # Create second session with different provider
203        session2 = SAMLSession.objects.create(
204            provider=self.provider2,
205            user=self.user,
206            session=self.auth_session,
207            session_index=generate_id(),
208            name_id=self.name_id,
209            name_id_format=self.name_id_format,
210            expires=self.expires,
211            expiring=True,
212        )
213
214        # Verify both sessions exist
215        user_sessions = SAMLSession.objects.filter(user=self.user)
216        self.assertEqual(user_sessions.count(), 2)
217        self.assertIn(session1, user_sessions)
218        self.assertIn(session2, user_sessions)

Test that a user can have multiple SAML sessions with different providers

def test_session_expiry_tracking(self):
220    def test_session_expiry_tracking(self):
221        """Test that session expiry time is properly stored"""
222        # Create session with specific expiry
223        future_time = timezone.now() + timedelta(hours=24)
224        saml_session = SAMLSession.objects.create(
225            provider=self.provider,
226            user=self.user,
227            session=self.auth_session,
228            session_index=self.session_index,
229            name_id=self.name_id,
230            name_id_format=self.name_id_format,
231            expires=future_time,
232            expiring=True,
233        )
234
235        # Verify expiry time
236        self.assertEqual(saml_session.expires, future_time)
237
238        # Check if session is expired (ExpiringModel behavior)
239        self.assertFalse(saml_session.is_expired)
240
241        # Create an expired session
242        past_time = timezone.now() - timedelta(hours=1)
243        expired_session = SAMLSession.objects.create(
244            provider=self.provider2,
245            user=self.user,
246            session=self.auth_session,
247            session_index=generate_id(),
248            name_id=self.name_id,
249            name_id_format=self.name_id_format,
250            expires=past_time,
251            expiring=True,
252        )
253
254        # Check if marked as expired
255        self.assertTrue(expired_session.is_expired)

Test that session expiry time is properly stored

def test_name_id_format_optional(self):
257    def test_name_id_format_optional(self):
258        """Test that name_id_format is optional (can be blank)"""
259        # Create session without name_id_format
260        saml_session = SAMLSession.objects.create(
261            provider=self.provider,
262            user=self.user,
263            session=self.auth_session,
264            session_index=self.session_index,
265            name_id=self.name_id,
266            name_id_format="",  # Blank format
267            expires=self.expires,
268            expiring=True,
269        )
270
271        # Verify it was created successfully
272        self.assertIsNotNone(saml_session.pk)
273        self.assertEqual(saml_session.name_id_format, "")

Test that name_id_format is optional (can be blank)

def test_query_sessions_by_provider(self):
275    def test_query_sessions_by_provider(self):
276        """Test querying sessions by provider"""
277        # Create sessions for different providers
278        session1 = SAMLSession.objects.create(
279            provider=self.provider,
280            user=self.user,
281            session=self.auth_session,
282            session_index=generate_id(),
283            name_id=self.name_id,
284            name_id_format=self.name_id_format,
285            expires=self.expires,
286            expiring=True,
287        )
288
289        session2 = SAMLSession.objects.create(
290            provider=self.provider2,
291            user=self.user,
292            session=self.auth_session,
293            session_index=generate_id(),
294            name_id=self.name_id,
295            name_id_format=self.name_id_format,
296            expires=self.expires,
297            expiring=True,
298        )
299
300        # Query by provider
301        provider1_sessions = SAMLSession.objects.filter(provider=self.provider)
302        self.assertEqual(provider1_sessions.count(), 1)
303        self.assertEqual(provider1_sessions.first(), session1)
304
305        provider2_sessions = SAMLSession.objects.filter(provider=self.provider2)
306        self.assertEqual(provider2_sessions.count(), 1)
307        self.assertEqual(provider2_sessions.first(), session2)

Test querying sessions by provider

def test_serializer_property(self):
309    def test_serializer_property(self):
310        """Test that the serializer property returns the correct serializer"""
311        saml_session = SAMLSession.objects.create(
312            provider=self.provider,
313            user=self.user,
314            session=self.auth_session,
315            session_index=self.session_index,
316            name_id=self.name_id,
317            name_id_format=self.name_id_format,
318            expires=self.expires,
319            expiring=True,
320        )
321
322        # Check serializer property
323        self.assertEqual(saml_session.serializer, SAMLSessionSerializer)

Test that the serializer property returns the correct serializer

def test_bulk_delete_sessions_for_user(self):
325    def test_bulk_delete_sessions_for_user(self):
326        """Test bulk deletion of all SAML sessions for a user"""
327        # Create multiple sessions
328        for i in range(3):
329            SAMLSession.objects.create(
330                provider=self.provider if i % 2 == 0 else self.provider2,
331                user=self.user,
332                session=self.auth_session,
333                session_index=generate_id(),
334                name_id=self.name_id,
335                name_id_format=self.name_id_format,
336                expires=self.expires,
337                expiring=True,
338            )
339
340        # Verify sessions exist
341        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 3)
342
343        # Delete all sessions for the user
344        deleted_count, _ = SAMLSession.objects.filter(user=self.user).delete()
345
346        # Verify all were deleted
347        self.assertEqual(deleted_count, 3)
348        self.assertEqual(SAMLSession.objects.filter(user=self.user).count(), 0)

Test bulk deletion of all SAML sessions for a user