|
21 | 21 |
|
22 | 22 | from satosa.backends.saml2 import SAMLBackend |
23 | 23 | from satosa.context import Context |
| 24 | +from satosa.exception import SATOSAAuthenticationError |
| 25 | +from satosa.exception import SATOSAMissingStateError |
24 | 26 | from satosa.internal import InternalData |
25 | 27 | from tests.users import USERS |
26 | 28 | from tests.util import FakeIdP, create_metadata_from_config_dict, FakeSP |
@@ -132,7 +134,7 @@ def test_full_flow(self, context, idp_conf, sp_conf): |
132 | 134 | disco_resp = parse_qs(urlparse(resp.message).query) |
133 | 135 | info = parse_qs(urlparse(disco_resp["return"][0]).query) |
134 | 136 | info["entityID"] = idp_conf["entityid"] |
135 | | - request_context = context |
| 137 | + request_context = Context() |
136 | 138 | request_context.request = info |
137 | 139 | request_context.state = context.state |
138 | 140 |
|
@@ -241,43 +243,72 @@ def test_unknown_or_no_hostname_selects_first_acs( |
241 | 243 |
|
242 | 244 | def test_authn_response(self, context, idp_conf, sp_conf): |
243 | 245 | response_binding = BINDING_HTTP_REDIRECT |
244 | | - fakesp = FakeSP(SPConfig().load(sp_conf)) |
245 | | - fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf)) |
246 | | - destination, request_params = fakesp.make_auth_req(idp_conf["entityid"]) |
247 | | - url, auth_resp = fakeidp.handle_auth_req(request_params["SAMLRequest"], request_params["RelayState"], |
248 | | - BINDING_HTTP_REDIRECT, |
249 | | - "testuser1", response_binding=response_binding) |
250 | | - |
| 246 | + request_params, auth_resp = self._perform_request_response( |
| 247 | + idp_conf, sp_conf, response_binding |
| 248 | + ) |
251 | 249 | context.request = auth_resp |
252 | 250 | context.state[self.samlbackend.name] = {"relay_state": request_params["RelayState"]} |
253 | 251 | self.samlbackend.authn_response(context, response_binding) |
254 | 252 |
|
255 | 253 | context, internal_resp = self.samlbackend.auth_callback_func.call_args[0] |
256 | 254 | assert_authn_response(internal_resp) |
257 | 255 |
|
258 | | - @pytest.mark.skipif( |
259 | | - saml2.__version__ < '4.6.1', |
260 | | - reason="Optional NameID needs pysaml2 v4.6.1 or higher") |
261 | | - def test_authn_response_no_name_id(self, context, idp_conf, sp_conf): |
| 256 | + def _perform_request_response( |
| 257 | + self, idp_conf, sp_conf, response_binding, receive_nameid=True |
| 258 | + ): |
| 259 | + fakesp = FakeSP(SPConfig().load(sp_conf)) |
| 260 | + fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf)) |
| 261 | + destination, request_params = fakesp.make_auth_req(idp_conf["entityid"]) |
| 262 | + auth_resp_func = ( |
| 263 | + fakeidp.handle_auth_req |
| 264 | + if receive_nameid |
| 265 | + else fakeidp.handle_auth_req_no_name_id |
| 266 | + ) |
| 267 | + url, auth_resp = auth_resp_func( |
| 268 | + request_params["SAMLRequest"], |
| 269 | + request_params["RelayState"], |
| 270 | + BINDING_HTTP_REDIRECT, |
| 271 | + "testuser1", |
| 272 | + response_binding=response_binding, |
| 273 | + ) |
| 274 | + |
| 275 | + return request_params, auth_resp |
| 276 | + |
| 277 | + def test_no_state_raises_error(self, context, idp_conf, sp_conf): |
262 | 278 | response_binding = BINDING_HTTP_REDIRECT |
| 279 | + request_params, auth_resp = self._perform_request_response( |
| 280 | + idp_conf, sp_conf, response_binding |
| 281 | + ) |
| 282 | + context.request = auth_resp |
| 283 | + # not setting context.state[self.samlbackend.name] |
| 284 | + # to simulate a request with lost state |
263 | 285 |
|
264 | | - fakesp_conf = SPConfig().load(sp_conf) |
265 | | - fakesp = FakeSP(fakesp_conf) |
| 286 | + with pytest.raises(SATOSAMissingStateError): |
| 287 | + self.samlbackend.authn_response(context, response_binding) |
266 | 288 |
|
267 | | - fakeidp_conf = IdPConfig().load(idp_conf) |
268 | | - fakeidp = FakeIdP(USERS, config=fakeidp_conf) |
| 289 | + def test_no_relay_state_raises_error(self, context, idp_conf, sp_conf): |
| 290 | + response_binding = BINDING_HTTP_REDIRECT |
| 291 | + request_params, auth_resp = self._perform_request_response( |
| 292 | + idp_conf, sp_conf, response_binding |
| 293 | + ) |
| 294 | + context.request = auth_resp |
| 295 | + # not setting context.state[self.samlbackend.name]["relay_state"] |
| 296 | + # to simulate a request without a relay state |
| 297 | + context.state[self.samlbackend.name] = {} |
269 | 298 |
|
270 | | - destination, request_params = fakesp.make_auth_req( |
271 | | - idp_conf["entityid"]) |
| 299 | + with pytest.raises(SATOSAAuthenticationError): |
| 300 | + self.samlbackend.authn_response(context, response_binding) |
272 | 301 |
|
273 | | - # Use the fake IdP to mock up an authentication request that has no |
274 | | - # <NameID> element. |
275 | | - url, auth_resp = fakeidp.handle_auth_req_no_name_id( |
276 | | - request_params["SAMLRequest"], |
277 | | - request_params["RelayState"], |
278 | | - BINDING_HTTP_REDIRECT, |
279 | | - "testuser1", |
280 | | - response_binding=response_binding) |
| 302 | + @pytest.mark.skipif( |
| 303 | + saml2.__version__ < '4.6.1', |
| 304 | + reason="Optional NameID needs pysaml2 v4.6.1 or higher" |
| 305 | + ) |
| 306 | + def test_authn_response_no_name_id(self, context, idp_conf, sp_conf): |
| 307 | + response_binding = BINDING_HTTP_REDIRECT |
| 308 | + |
| 309 | + request_params, auth_resp = self._perform_request_response( |
| 310 | + idp_conf, sp_conf, response_binding, receive_nameid=False |
| 311 | + ) |
281 | 312 |
|
282 | 313 | backend = self.samlbackend |
283 | 314 |
|
|
0 commit comments