authentik.providers.saml.tests.test_tasks
Tests for SAML provider tasks
1"""Tests for SAML provider tasks""" 2 3from unittest.mock import MagicMock, patch 4 5from django.test import TestCase 6from requests.exceptions import ConnectionError, HTTPError 7 8from authentik.common.saml.constants import SAML_NAME_ID_FORMAT_EMAIL 9from authentik.core.tests.utils import create_test_cert, create_test_flow 10from authentik.providers.saml.models import SAMLProvider 11from authentik.providers.saml.tasks import ( 12 send_post_logout_request, 13 send_saml_logout_request, 14 send_saml_logout_response, 15) 16 17 18class TestSendSamlLogoutResponse(TestCase): 19 """Tests for send_saml_logout_response task""" 20 21 def setUp(self): 22 """Set up test fixtures""" 23 self.cert = create_test_cert() 24 self.flow = create_test_flow() 25 26 self.provider = SAMLProvider.objects.create( 27 name="test-provider", 28 authorization_flow=self.flow, 29 acs_url="https://sp.example.com/acs", 30 sls_url="https://sp.example.com/sls", 31 issuer="https://idp.example.com", 32 signing_kp=self.cert, 33 ) 34 35 @patch("authentik.providers.saml.tasks.requests.post") 36 def test_successful_logout_response(self, mock_post): 37 """Test successful POST to SP returns True""" 38 mock_response = MagicMock() 39 mock_response.status_code = 200 40 mock_response.raise_for_status = MagicMock() 41 mock_post.return_value = mock_response 42 43 result = send_saml_logout_response( 44 provider_pk=self.provider.pk, 45 sls_url=self.provider.sls_url, 46 logout_request_id="test-request-id", 47 relay_state="https://sp.example.com/return", 48 ) 49 50 self.assertTrue(result) 51 mock_post.assert_called_once() 52 53 # Verify the POST was made with correct data 54 call_kwargs = mock_post.call_args[1] 55 self.assertEqual(call_kwargs["timeout"], 10) 56 self.assertEqual( 57 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 58 ) 59 60 # Verify form data contains SAMLResponse and RelayState 61 form_data = call_kwargs["data"] 62 self.assertIn("SAMLResponse", form_data) 63 self.assertIn("RelayState", form_data) 64 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return") 65 66 @patch("authentik.providers.saml.tasks.requests.post") 67 def test_successful_logout_response_no_relay_state(self, mock_post): 68 """Test successful POST without relay_state""" 69 mock_response = MagicMock() 70 mock_response.status_code = 200 71 mock_response.raise_for_status = MagicMock() 72 mock_post.return_value = mock_response 73 74 result = send_saml_logout_response( 75 provider_pk=self.provider.pk, 76 sls_url=self.provider.sls_url, 77 logout_request_id="test-request-id", 78 relay_state=None, 79 ) 80 81 self.assertTrue(result) 82 83 # Verify form data does not contain RelayState 84 form_data = mock_post.call_args[1]["data"] 85 self.assertIn("SAMLResponse", form_data) 86 self.assertNotIn("RelayState", form_data) 87 88 def test_provider_not_found(self): 89 """Test returns False when provider doesn't exist""" 90 result = send_saml_logout_response( 91 provider_pk=99999, # Non-existent provider 92 sls_url="https://sp.example.com/sls", 93 logout_request_id="test-request-id", 94 relay_state=None, 95 ) 96 97 self.assertFalse(result) 98 99 @patch("authentik.providers.saml.tasks.Event") 100 @patch("authentik.providers.saml.tasks.requests.post") 101 def test_http_error_creates_event(self, mock_post, mock_event_class): 102 """Test HTTP error creates an error event""" 103 mock_response = MagicMock() 104 mock_response.status_code = 500 105 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 106 mock_post.return_value = mock_response 107 108 mock_event = MagicMock() 109 mock_event_class.new.return_value = mock_event 110 111 result = send_saml_logout_response( 112 provider_pk=self.provider.pk, 113 sls_url=self.provider.sls_url, 114 logout_request_id="test-request-id", 115 relay_state=None, 116 ) 117 118 self.assertFalse(result) 119 120 # Verify error event was created 121 mock_event_class.new.assert_called_once() 122 call_kwargs = mock_event_class.new.call_args[1] 123 self.assertIn("Backchannel logout response failed", call_kwargs["message"]) 124 mock_event.save.assert_called_once() 125 126 127class TestSendSamlLogoutRequest(TestCase): 128 """Tests for send_saml_logout_request task""" 129 130 def setUp(self): 131 """Set up test fixtures""" 132 self.cert = create_test_cert() 133 self.flow = create_test_flow() 134 135 self.provider = SAMLProvider.objects.create( 136 name="test-provider", 137 authorization_flow=self.flow, 138 acs_url="https://sp.example.com/acs", 139 sls_url="https://sp.example.com/sls", 140 issuer="https://idp.example.com", 141 signing_kp=self.cert, 142 ) 143 144 @patch("authentik.providers.saml.tasks.requests.post") 145 def test_successful_logout_request(self, mock_post): 146 """Test successful POST logout request returns True""" 147 mock_response = MagicMock() 148 mock_response.status_code = 200 149 mock_response.raise_for_status = MagicMock() 150 mock_post.return_value = mock_response 151 152 result = send_saml_logout_request( 153 provider_pk=self.provider.pk, 154 sls_url=self.provider.sls_url, 155 name_id="test@example.com", 156 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 157 session_index="test-session-123", 158 ) 159 160 self.assertTrue(result) 161 mock_post.assert_called_once() 162 163 # Verify the POST was made with correct data 164 call_kwargs = mock_post.call_args[1] 165 self.assertEqual(call_kwargs["timeout"], 10) 166 self.assertEqual( 167 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 168 ) 169 170 # Verify form data contains SAMLRequest 171 form_data = call_kwargs["data"] 172 self.assertIn("SAMLRequest", form_data) 173 174 def test_provider_not_found(self): 175 """Test returns False when provider doesn't exist""" 176 result = send_saml_logout_request( 177 provider_pk=99999, # Non-existent provider 178 sls_url="https://sp.example.com/sls", 179 name_id="test@example.com", 180 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 181 session_index="test-session-123", 182 ) 183 184 self.assertFalse(result) 185 186 @patch("authentik.providers.saml.tasks.requests.post") 187 def test_http_error_raises(self, mock_post): 188 """Test HTTP error raises exception (no try/catch in send_post_logout_request)""" 189 mock_response = MagicMock() 190 mock_response.status_code = 500 191 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 192 mock_post.return_value = mock_response 193 194 with self.assertRaises(HTTPError): 195 send_saml_logout_request( 196 provider_pk=self.provider.pk, 197 sls_url=self.provider.sls_url, 198 name_id="test@example.com", 199 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 200 session_index="test-session-123", 201 ) 202 203 204class TestSendPostLogoutRequest(TestCase): 205 """Tests for send_post_logout_request function""" 206 207 def setUp(self): 208 """Set up test fixtures""" 209 self.cert = create_test_cert() 210 self.flow = create_test_flow() 211 212 self.provider = SAMLProvider.objects.create( 213 name="test-provider", 214 authorization_flow=self.flow, 215 acs_url="https://sp.example.com/acs", 216 sls_url="https://sp.example.com/sls", 217 issuer="https://idp.example.com", 218 signing_kp=self.cert, 219 ) 220 221 @patch("authentik.providers.saml.tasks.requests.post") 222 def test_successful_post(self, mock_post): 223 """Test successful POST returns True""" 224 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 225 226 mock_response = MagicMock() 227 mock_response.status_code = 200 228 mock_response.raise_for_status = MagicMock() 229 mock_post.return_value = mock_response 230 231 processor = LogoutRequestProcessor( 232 provider=self.provider, 233 user=None, 234 destination=self.provider.sls_url, 235 name_id="test@example.com", 236 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 237 session_index="test-session-123", 238 ) 239 240 result = send_post_logout_request(self.provider, processor) 241 242 self.assertTrue(result) 243 mock_post.assert_called_once() 244 245 @patch("authentik.providers.saml.tasks.requests.post") 246 def test_with_relay_state(self, mock_post): 247 """Test POST includes RelayState when present""" 248 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 249 250 mock_response = MagicMock() 251 mock_response.status_code = 200 252 mock_response.raise_for_status = MagicMock() 253 mock_post.return_value = mock_response 254 255 processor = LogoutRequestProcessor( 256 provider=self.provider, 257 user=None, 258 destination=self.provider.sls_url, 259 name_id="test@example.com", 260 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 261 session_index="test-session-123", 262 relay_state="https://sp.example.com/return", 263 ) 264 265 result = send_post_logout_request(self.provider, processor) 266 267 self.assertTrue(result) 268 269 # Verify RelayState is included 270 form_data = mock_post.call_args[1]["data"] 271 self.assertIn("RelayState", form_data) 272 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return") 273 274 @patch("authentik.providers.saml.tasks.requests.post") 275 def test_connection_error_raises(self, mock_post): 276 """Test connection error raises exception""" 277 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 278 279 mock_post.side_effect = ConnectionError("Connection refused") 280 281 processor = LogoutRequestProcessor( 282 provider=self.provider, 283 user=None, 284 destination=self.provider.sls_url, 285 name_id="test@example.com", 286 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 287 session_index="test-session-123", 288 ) 289 290 with self.assertRaises(ConnectionError): 291 send_post_logout_request(self.provider, processor)
class
TestSendSamlLogoutResponse(django.test.testcases.TestCase):
19class TestSendSamlLogoutResponse(TestCase): 20 """Tests for send_saml_logout_response task""" 21 22 def setUp(self): 23 """Set up test fixtures""" 24 self.cert = create_test_cert() 25 self.flow = create_test_flow() 26 27 self.provider = SAMLProvider.objects.create( 28 name="test-provider", 29 authorization_flow=self.flow, 30 acs_url="https://sp.example.com/acs", 31 sls_url="https://sp.example.com/sls", 32 issuer="https://idp.example.com", 33 signing_kp=self.cert, 34 ) 35 36 @patch("authentik.providers.saml.tasks.requests.post") 37 def test_successful_logout_response(self, mock_post): 38 """Test successful POST to SP returns True""" 39 mock_response = MagicMock() 40 mock_response.status_code = 200 41 mock_response.raise_for_status = MagicMock() 42 mock_post.return_value = mock_response 43 44 result = send_saml_logout_response( 45 provider_pk=self.provider.pk, 46 sls_url=self.provider.sls_url, 47 logout_request_id="test-request-id", 48 relay_state="https://sp.example.com/return", 49 ) 50 51 self.assertTrue(result) 52 mock_post.assert_called_once() 53 54 # Verify the POST was made with correct data 55 call_kwargs = mock_post.call_args[1] 56 self.assertEqual(call_kwargs["timeout"], 10) 57 self.assertEqual( 58 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 59 ) 60 61 # Verify form data contains SAMLResponse and RelayState 62 form_data = call_kwargs["data"] 63 self.assertIn("SAMLResponse", form_data) 64 self.assertIn("RelayState", form_data) 65 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return") 66 67 @patch("authentik.providers.saml.tasks.requests.post") 68 def test_successful_logout_response_no_relay_state(self, mock_post): 69 """Test successful POST without relay_state""" 70 mock_response = MagicMock() 71 mock_response.status_code = 200 72 mock_response.raise_for_status = MagicMock() 73 mock_post.return_value = mock_response 74 75 result = send_saml_logout_response( 76 provider_pk=self.provider.pk, 77 sls_url=self.provider.sls_url, 78 logout_request_id="test-request-id", 79 relay_state=None, 80 ) 81 82 self.assertTrue(result) 83 84 # Verify form data does not contain RelayState 85 form_data = mock_post.call_args[1]["data"] 86 self.assertIn("SAMLResponse", form_data) 87 self.assertNotIn("RelayState", form_data) 88 89 def test_provider_not_found(self): 90 """Test returns False when provider doesn't exist""" 91 result = send_saml_logout_response( 92 provider_pk=99999, # Non-existent provider 93 sls_url="https://sp.example.com/sls", 94 logout_request_id="test-request-id", 95 relay_state=None, 96 ) 97 98 self.assertFalse(result) 99 100 @patch("authentik.providers.saml.tasks.Event") 101 @patch("authentik.providers.saml.tasks.requests.post") 102 def test_http_error_creates_event(self, mock_post, mock_event_class): 103 """Test HTTP error creates an error event""" 104 mock_response = MagicMock() 105 mock_response.status_code = 500 106 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 107 mock_post.return_value = mock_response 108 109 mock_event = MagicMock() 110 mock_event_class.new.return_value = mock_event 111 112 result = send_saml_logout_response( 113 provider_pk=self.provider.pk, 114 sls_url=self.provider.sls_url, 115 logout_request_id="test-request-id", 116 relay_state=None, 117 ) 118 119 self.assertFalse(result) 120 121 # Verify error event was created 122 mock_event_class.new.assert_called_once() 123 call_kwargs = mock_event_class.new.call_args[1] 124 self.assertIn("Backchannel logout response failed", call_kwargs["message"]) 125 mock_event.save.assert_called_once()
Tests for send_saml_logout_response task
def
setUp(self):
22 def setUp(self): 23 """Set up test fixtures""" 24 self.cert = create_test_cert() 25 self.flow = create_test_flow() 26 27 self.provider = SAMLProvider.objects.create( 28 name="test-provider", 29 authorization_flow=self.flow, 30 acs_url="https://sp.example.com/acs", 31 sls_url="https://sp.example.com/sls", 32 issuer="https://idp.example.com", 33 signing_kp=self.cert, 34 )
Set up test fixtures
@patch('authentik.providers.saml.tasks.requests.post')
def
test_successful_logout_response(self, mock_post):
36 @patch("authentik.providers.saml.tasks.requests.post") 37 def test_successful_logout_response(self, mock_post): 38 """Test successful POST to SP returns True""" 39 mock_response = MagicMock() 40 mock_response.status_code = 200 41 mock_response.raise_for_status = MagicMock() 42 mock_post.return_value = mock_response 43 44 result = send_saml_logout_response( 45 provider_pk=self.provider.pk, 46 sls_url=self.provider.sls_url, 47 logout_request_id="test-request-id", 48 relay_state="https://sp.example.com/return", 49 ) 50 51 self.assertTrue(result) 52 mock_post.assert_called_once() 53 54 # Verify the POST was made with correct data 55 call_kwargs = mock_post.call_args[1] 56 self.assertEqual(call_kwargs["timeout"], 10) 57 self.assertEqual( 58 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 59 ) 60 61 # Verify form data contains SAMLResponse and RelayState 62 form_data = call_kwargs["data"] 63 self.assertIn("SAMLResponse", form_data) 64 self.assertIn("RelayState", form_data) 65 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return")
Test successful POST to SP returns True
@patch('authentik.providers.saml.tasks.requests.post')
def
test_successful_logout_response_no_relay_state(self, mock_post):
67 @patch("authentik.providers.saml.tasks.requests.post") 68 def test_successful_logout_response_no_relay_state(self, mock_post): 69 """Test successful POST without relay_state""" 70 mock_response = MagicMock() 71 mock_response.status_code = 200 72 mock_response.raise_for_status = MagicMock() 73 mock_post.return_value = mock_response 74 75 result = send_saml_logout_response( 76 provider_pk=self.provider.pk, 77 sls_url=self.provider.sls_url, 78 logout_request_id="test-request-id", 79 relay_state=None, 80 ) 81 82 self.assertTrue(result) 83 84 # Verify form data does not contain RelayState 85 form_data = mock_post.call_args[1]["data"] 86 self.assertIn("SAMLResponse", form_data) 87 self.assertNotIn("RelayState", form_data)
Test successful POST without relay_state
def
test_provider_not_found(self):
89 def test_provider_not_found(self): 90 """Test returns False when provider doesn't exist""" 91 result = send_saml_logout_response( 92 provider_pk=99999, # Non-existent provider 93 sls_url="https://sp.example.com/sls", 94 logout_request_id="test-request-id", 95 relay_state=None, 96 ) 97 98 self.assertFalse(result)
Test returns False when provider doesn't exist
@patch('authentik.providers.saml.tasks.Event')
@patch('authentik.providers.saml.tasks.requests.post')
def
test_http_error_creates_event(self, mock_post, mock_event_class):
100 @patch("authentik.providers.saml.tasks.Event") 101 @patch("authentik.providers.saml.tasks.requests.post") 102 def test_http_error_creates_event(self, mock_post, mock_event_class): 103 """Test HTTP error creates an error event""" 104 mock_response = MagicMock() 105 mock_response.status_code = 500 106 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 107 mock_post.return_value = mock_response 108 109 mock_event = MagicMock() 110 mock_event_class.new.return_value = mock_event 111 112 result = send_saml_logout_response( 113 provider_pk=self.provider.pk, 114 sls_url=self.provider.sls_url, 115 logout_request_id="test-request-id", 116 relay_state=None, 117 ) 118 119 self.assertFalse(result) 120 121 # Verify error event was created 122 mock_event_class.new.assert_called_once() 123 call_kwargs = mock_event_class.new.call_args[1] 124 self.assertIn("Backchannel logout response failed", call_kwargs["message"]) 125 mock_event.save.assert_called_once()
Test HTTP error creates an error event
class
TestSendSamlLogoutRequest(django.test.testcases.TestCase):
128class TestSendSamlLogoutRequest(TestCase): 129 """Tests for send_saml_logout_request task""" 130 131 def setUp(self): 132 """Set up test fixtures""" 133 self.cert = create_test_cert() 134 self.flow = create_test_flow() 135 136 self.provider = SAMLProvider.objects.create( 137 name="test-provider", 138 authorization_flow=self.flow, 139 acs_url="https://sp.example.com/acs", 140 sls_url="https://sp.example.com/sls", 141 issuer="https://idp.example.com", 142 signing_kp=self.cert, 143 ) 144 145 @patch("authentik.providers.saml.tasks.requests.post") 146 def test_successful_logout_request(self, mock_post): 147 """Test successful POST logout request returns True""" 148 mock_response = MagicMock() 149 mock_response.status_code = 200 150 mock_response.raise_for_status = MagicMock() 151 mock_post.return_value = mock_response 152 153 result = send_saml_logout_request( 154 provider_pk=self.provider.pk, 155 sls_url=self.provider.sls_url, 156 name_id="test@example.com", 157 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 158 session_index="test-session-123", 159 ) 160 161 self.assertTrue(result) 162 mock_post.assert_called_once() 163 164 # Verify the POST was made with correct data 165 call_kwargs = mock_post.call_args[1] 166 self.assertEqual(call_kwargs["timeout"], 10) 167 self.assertEqual( 168 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 169 ) 170 171 # Verify form data contains SAMLRequest 172 form_data = call_kwargs["data"] 173 self.assertIn("SAMLRequest", form_data) 174 175 def test_provider_not_found(self): 176 """Test returns False when provider doesn't exist""" 177 result = send_saml_logout_request( 178 provider_pk=99999, # Non-existent provider 179 sls_url="https://sp.example.com/sls", 180 name_id="test@example.com", 181 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 182 session_index="test-session-123", 183 ) 184 185 self.assertFalse(result) 186 187 @patch("authentik.providers.saml.tasks.requests.post") 188 def test_http_error_raises(self, mock_post): 189 """Test HTTP error raises exception (no try/catch in send_post_logout_request)""" 190 mock_response = MagicMock() 191 mock_response.status_code = 500 192 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 193 mock_post.return_value = mock_response 194 195 with self.assertRaises(HTTPError): 196 send_saml_logout_request( 197 provider_pk=self.provider.pk, 198 sls_url=self.provider.sls_url, 199 name_id="test@example.com", 200 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 201 session_index="test-session-123", 202 )
Tests for send_saml_logout_request task
def
setUp(self):
131 def setUp(self): 132 """Set up test fixtures""" 133 self.cert = create_test_cert() 134 self.flow = create_test_flow() 135 136 self.provider = SAMLProvider.objects.create( 137 name="test-provider", 138 authorization_flow=self.flow, 139 acs_url="https://sp.example.com/acs", 140 sls_url="https://sp.example.com/sls", 141 issuer="https://idp.example.com", 142 signing_kp=self.cert, 143 )
Set up test fixtures
@patch('authentik.providers.saml.tasks.requests.post')
def
test_successful_logout_request(self, mock_post):
145 @patch("authentik.providers.saml.tasks.requests.post") 146 def test_successful_logout_request(self, mock_post): 147 """Test successful POST logout request returns True""" 148 mock_response = MagicMock() 149 mock_response.status_code = 200 150 mock_response.raise_for_status = MagicMock() 151 mock_post.return_value = mock_response 152 153 result = send_saml_logout_request( 154 provider_pk=self.provider.pk, 155 sls_url=self.provider.sls_url, 156 name_id="test@example.com", 157 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 158 session_index="test-session-123", 159 ) 160 161 self.assertTrue(result) 162 mock_post.assert_called_once() 163 164 # Verify the POST was made with correct data 165 call_kwargs = mock_post.call_args[1] 166 self.assertEqual(call_kwargs["timeout"], 10) 167 self.assertEqual( 168 call_kwargs["headers"]["Content-Type"], "application/x-www-form-urlencoded" 169 ) 170 171 # Verify form data contains SAMLRequest 172 form_data = call_kwargs["data"] 173 self.assertIn("SAMLRequest", form_data)
Test successful POST logout request returns True
def
test_provider_not_found(self):
175 def test_provider_not_found(self): 176 """Test returns False when provider doesn't exist""" 177 result = send_saml_logout_request( 178 provider_pk=99999, # Non-existent provider 179 sls_url="https://sp.example.com/sls", 180 name_id="test@example.com", 181 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 182 session_index="test-session-123", 183 ) 184 185 self.assertFalse(result)
Test returns False when provider doesn't exist
@patch('authentik.providers.saml.tasks.requests.post')
def
test_http_error_raises(self, mock_post):
187 @patch("authentik.providers.saml.tasks.requests.post") 188 def test_http_error_raises(self, mock_post): 189 """Test HTTP error raises exception (no try/catch in send_post_logout_request)""" 190 mock_response = MagicMock() 191 mock_response.status_code = 500 192 mock_response.raise_for_status.side_effect = HTTPError("500 Server Error") 193 mock_post.return_value = mock_response 194 195 with self.assertRaises(HTTPError): 196 send_saml_logout_request( 197 provider_pk=self.provider.pk, 198 sls_url=self.provider.sls_url, 199 name_id="test@example.com", 200 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 201 session_index="test-session-123", 202 )
Test HTTP error raises exception (no try/catch in send_post_logout_request)
class
TestSendPostLogoutRequest(django.test.testcases.TestCase):
205class TestSendPostLogoutRequest(TestCase): 206 """Tests for send_post_logout_request function""" 207 208 def setUp(self): 209 """Set up test fixtures""" 210 self.cert = create_test_cert() 211 self.flow = create_test_flow() 212 213 self.provider = SAMLProvider.objects.create( 214 name="test-provider", 215 authorization_flow=self.flow, 216 acs_url="https://sp.example.com/acs", 217 sls_url="https://sp.example.com/sls", 218 issuer="https://idp.example.com", 219 signing_kp=self.cert, 220 ) 221 222 @patch("authentik.providers.saml.tasks.requests.post") 223 def test_successful_post(self, mock_post): 224 """Test successful POST returns True""" 225 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 226 227 mock_response = MagicMock() 228 mock_response.status_code = 200 229 mock_response.raise_for_status = MagicMock() 230 mock_post.return_value = mock_response 231 232 processor = LogoutRequestProcessor( 233 provider=self.provider, 234 user=None, 235 destination=self.provider.sls_url, 236 name_id="test@example.com", 237 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 238 session_index="test-session-123", 239 ) 240 241 result = send_post_logout_request(self.provider, processor) 242 243 self.assertTrue(result) 244 mock_post.assert_called_once() 245 246 @patch("authentik.providers.saml.tasks.requests.post") 247 def test_with_relay_state(self, mock_post): 248 """Test POST includes RelayState when present""" 249 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 250 251 mock_response = MagicMock() 252 mock_response.status_code = 200 253 mock_response.raise_for_status = MagicMock() 254 mock_post.return_value = mock_response 255 256 processor = LogoutRequestProcessor( 257 provider=self.provider, 258 user=None, 259 destination=self.provider.sls_url, 260 name_id="test@example.com", 261 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 262 session_index="test-session-123", 263 relay_state="https://sp.example.com/return", 264 ) 265 266 result = send_post_logout_request(self.provider, processor) 267 268 self.assertTrue(result) 269 270 # Verify RelayState is included 271 form_data = mock_post.call_args[1]["data"] 272 self.assertIn("RelayState", form_data) 273 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return") 274 275 @patch("authentik.providers.saml.tasks.requests.post") 276 def test_connection_error_raises(self, mock_post): 277 """Test connection error raises exception""" 278 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 279 280 mock_post.side_effect = ConnectionError("Connection refused") 281 282 processor = LogoutRequestProcessor( 283 provider=self.provider, 284 user=None, 285 destination=self.provider.sls_url, 286 name_id="test@example.com", 287 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 288 session_index="test-session-123", 289 ) 290 291 with self.assertRaises(ConnectionError): 292 send_post_logout_request(self.provider, processor)
Tests for send_post_logout_request function
def
setUp(self):
208 def setUp(self): 209 """Set up test fixtures""" 210 self.cert = create_test_cert() 211 self.flow = create_test_flow() 212 213 self.provider = SAMLProvider.objects.create( 214 name="test-provider", 215 authorization_flow=self.flow, 216 acs_url="https://sp.example.com/acs", 217 sls_url="https://sp.example.com/sls", 218 issuer="https://idp.example.com", 219 signing_kp=self.cert, 220 )
Set up test fixtures
@patch('authentik.providers.saml.tasks.requests.post')
def
test_successful_post(self, mock_post):
222 @patch("authentik.providers.saml.tasks.requests.post") 223 def test_successful_post(self, mock_post): 224 """Test successful POST returns True""" 225 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 226 227 mock_response = MagicMock() 228 mock_response.status_code = 200 229 mock_response.raise_for_status = MagicMock() 230 mock_post.return_value = mock_response 231 232 processor = LogoutRequestProcessor( 233 provider=self.provider, 234 user=None, 235 destination=self.provider.sls_url, 236 name_id="test@example.com", 237 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 238 session_index="test-session-123", 239 ) 240 241 result = send_post_logout_request(self.provider, processor) 242 243 self.assertTrue(result) 244 mock_post.assert_called_once()
Test successful POST returns True
@patch('authentik.providers.saml.tasks.requests.post')
def
test_with_relay_state(self, mock_post):
246 @patch("authentik.providers.saml.tasks.requests.post") 247 def test_with_relay_state(self, mock_post): 248 """Test POST includes RelayState when present""" 249 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 250 251 mock_response = MagicMock() 252 mock_response.status_code = 200 253 mock_response.raise_for_status = MagicMock() 254 mock_post.return_value = mock_response 255 256 processor = LogoutRequestProcessor( 257 provider=self.provider, 258 user=None, 259 destination=self.provider.sls_url, 260 name_id="test@example.com", 261 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 262 session_index="test-session-123", 263 relay_state="https://sp.example.com/return", 264 ) 265 266 result = send_post_logout_request(self.provider, processor) 267 268 self.assertTrue(result) 269 270 # Verify RelayState is included 271 form_data = mock_post.call_args[1]["data"] 272 self.assertIn("RelayState", form_data) 273 self.assertEqual(form_data["RelayState"], "https://sp.example.com/return")
Test POST includes RelayState when present
@patch('authentik.providers.saml.tasks.requests.post')
def
test_connection_error_raises(self, mock_post):
275 @patch("authentik.providers.saml.tasks.requests.post") 276 def test_connection_error_raises(self, mock_post): 277 """Test connection error raises exception""" 278 from authentik.providers.saml.processors.logout_request import LogoutRequestProcessor 279 280 mock_post.side_effect = ConnectionError("Connection refused") 281 282 processor = LogoutRequestProcessor( 283 provider=self.provider, 284 user=None, 285 destination=self.provider.sls_url, 286 name_id="test@example.com", 287 name_id_format=SAML_NAME_ID_FORMAT_EMAIL, 288 session_index="test-session-123", 289 ) 290 291 with self.assertRaises(ConnectionError): 292 send_post_logout_request(self.provider, processor)
Test connection error raises exception