Ejemplo n.º 1
0
    def test_authn_response_no_name_id(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT

        fakesp_conf = SPConfig().load(sp_conf, metadata_construction=False)
        fakesp = FakeSP(fakesp_conf)

        fakeidp_conf = IdPConfig().load(idp_conf, metadata_construction=False)
        fakeidp = FakeIdP(USERS, config=fakeidp_conf)

        destination, request_params = fakesp.make_auth_req(
            idp_conf["entityid"])

        # Use the fake IdP to mock up an authentication request that has no
        # <NameID> element.
        url, auth_resp = fakeidp.handle_auth_req_no_name_id(
            request_params["SAMLRequest"],
            request_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            "testuser1",
            response_binding=response_binding)

        backend = self.samlbackend

        context.request = auth_resp
        context.state[backend.name] = {
            "relay_state": request_params["RelayState"],
        }
        backend.authn_response(context, response_binding)

        context, internal_resp = backend.auth_callback_func.call_args[0]
        self.assert_authn_response(internal_resp)
        assert backend.name not in context.state
Ejemplo n.º 2
0
    def test_authn_response(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        fakeidp = FakeIdP(USERS,
                          config=IdPConfig().load(idp_conf,
                                                  metadata_construction=False))
        destination, request_params = fakesp.make_auth_req(
            idp_conf["entityid"])
        url, auth_resp = fakeidp.handle_auth_req(
            request_params["SAMLRequest"],
            request_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            "testuser1",
            response_binding=response_binding)

        context.request = auth_resp
        context.state[self.samlbackend.name] = {
            "relay_state": request_params["RelayState"]
        }
        self.samlbackend.authn_response(context, response_binding)

        context, internal_resp = self.samlbackend.auth_callback_func.call_args[
            0]
        self.assert_authn_response(internal_resp)
        assert self.samlbackend.name not in context.state
Ejemplo n.º 3
0
    def test_handle_authn_request_without_name_id_policy(
            self, idp_conf, sp_conf):
        """
        Performs a complete test for the module. The flow should be accepted.
        """
        context, samlfrontend = self.setup_for_authn_req(idp_conf, sp_conf, "")
        _, internal_req = samlfrontend.handle_authn_request(
            context, BINDING_HTTP_REDIRECT)
        assert internal_req.requestor == sp_conf["entityid"]

        auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z",
                                              "unittest_idp.xml")
        internal_response = InternalResponse(auth_info=auth_info)
        internal_response.set_user_id_hash_type(internal_req.user_id_hash_type)
        internal_response.add_attributes(USERS["testuser1"])

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(None,
                        config=SPConfig().load(sp_conf,
                                               metadata_construction=False))
        resp = fakesp.parse_authn_request_response(
            resp_dict['SAMLResponse'][0], BINDING_HTTP_REDIRECT)
        for key in resp.ava:
            assert USERS["testuser1"][key] == resp.ava[key]
Ejemplo n.º 4
0
    def setup_for_authn_req(self, context, idp_conf, sp_conf, nameid_format=None, relay_state="relay_state",
                            internal_attributes=INTERNAL_ATTRIBUTES, extra_config={},
                            subject=None):
        config = {"idp_config": idp_conf, "endpoints": ENDPOINTS}
        config.update(extra_config)
        sp_metadata_str = create_metadata_from_config_dict(sp_conf)
        idp_conf["metadata"]["inline"] = [sp_metadata_str]

        base_url = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        samlfrontend = SAMLFrontend(lambda ctx, internal_req: (ctx, internal_req),
                                    internal_attributes, config, base_url, "saml_frontend")
        samlfrontend.register_endpoints(["saml"])

        idp_metadata_str = create_metadata_from_config_dict(samlfrontend.idp_config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        destination, auth_req = fakesp.make_auth_req(
            samlfrontend.idp_config["entityid"],
            nameid_format,
            relay_state,
            subject=subject,
        )
        context.request = auth_req
        tmp_dict = {}
        for val in context.request:
            if isinstance(context.request[val], list):
                tmp_dict[val] = context.request[val][0]
            else:
                tmp_dict[val] = context.request[val]
        context.request = tmp_dict

        return samlfrontend
Ejemplo n.º 5
0
    def test_authn_response_no_name_id(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT

        fakesp_conf = SPConfig().load(sp_conf, metadata_construction=False)
        fakesp = FakeSP(fakesp_conf)

        fakeidp_conf = IdPConfig().load(idp_conf, metadata_construction=False)
        fakeidp = FakeIdP(USERS, config=fakeidp_conf)

        destination, request_params = fakesp.make_auth_req(
            idp_conf["entityid"])

        # Use the fake IdP to mock up an authentication request that has no
        # <NameID> element.
        url, auth_resp = fakeidp.handle_auth_req_no_name_id(
            request_params["SAMLRequest"],
            request_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            "testuser1",
            response_binding=response_binding)

        backend = self.samlbackend

        context.request = auth_resp
        context.state[backend.name] = {
            "relay_state": request_params["RelayState"],
        }
        backend.authn_response(context, response_binding)

        context, internal_resp = backend.auth_callback_func.call_args[0]
        assert_authn_response(internal_resp)
        assert backend.name not in context.state
Ejemplo n.º 6
0
    def get_auth_response(self, samlfrontend, context, internal_response,
                          sp_conf, idp_metadata_str):
        sp_config = SPConfig().load(sp_conf, metadata_construction=False)
        resp_args = {
            "name_id_policy":
            NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to":
            None,
            "destination":
            sp_config.endpoint("assertion_consumer_service",
                               binding=BINDING_HTTP_REDIRECT)[0],
            "sp_entity_id":
            sp_conf["entityid"],
            "binding":
            BINDING_HTTP_REDIRECT
        }
        request_state = samlfrontend._create_state_data(context, resp_args, "")
        context.state[samlfrontend.name] = request_state

        resp = samlfrontend.handle_authn_response(context, internal_response)

        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        fakesp = FakeSP(sp_config)
        resp_dict = parse_qs(urlparse(resp.message).query)
        return fakesp.parse_authn_request_response(
            resp_dict["SAMLResponse"][0], BINDING_HTTP_REDIRECT)
Ejemplo n.º 7
0
    def setup_for_authn_req(self, idp_conf, sp_conf, nameid_format):
        base = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        config = {"idp_config": idp_conf, "endpoints": ENDPOINTS, "base": base,
                  "state_id": "state_id"}
        sp_metadata_str = create_metadata_from_config_dict(sp_conf)
        idp_conf["metadata"]["inline"] = [sp_metadata_str]

        samlfrontend = SamlFrontend(lambda context, internal_req: (context, internal_req),
                                    INTERNAL_ATTRIBUTES, config)
        samlfrontend.register_endpoints(["saml"])

        idp_metadata_str = create_metadata_from_config_dict(samlfrontend.config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)

        fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False))
        context = Context()
        context.state = State()
        context.request = parse.parse_qs(
                urlparse(fakesp.make_auth_req(samlfrontend.config["entityid"], nameid_format)).query)
        tmp_dict = {}
        for val in context.request:
            if isinstance(context.request[val], list):
                tmp_dict[val] = context.request[val][0]
            else:
                tmp_dict[val] = context.request[val]
        context.request = tmp_dict

        return context, samlfrontend
Ejemplo n.º 8
0
    def setup_for_authn_req(self, context, idp_conf, sp_conf, nameid_format=None, relay_state="relay_state",
                            internal_attributes=INTERNAL_ATTRIBUTES, extra_config={}):
        config = {"idp_config": idp_conf, "endpoints": ENDPOINTS}
        config.update(extra_config)
        sp_metadata_str = create_metadata_from_config_dict(sp_conf)
        idp_conf["metadata"]["inline"] = [sp_metadata_str]

        base_url = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        samlfrontend = SAMLFrontend(lambda ctx, internal_req: (ctx, internal_req),
                                    internal_attributes, config, base_url, "saml_frontend")
        samlfrontend.register_endpoints(["saml"])

        idp_metadata_str = create_metadata_from_config_dict(samlfrontend.idp_config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        destination, auth_req = fakesp.make_auth_req(samlfrontend.idp_config["entityid"], nameid_format, relay_state)
        context.request = auth_req
        tmp_dict = {}
        for val in context.request:
            if isinstance(context.request[val], list):
                tmp_dict[val] = context.request[val][0]
            else:
                tmp_dict[val] = context.request[val]
        context.request = tmp_dict

        return samlfrontend
Ejemplo n.º 9
0
    def test_co_static_attributes(self, frontend, context, internal_response,
                                  idp_conf, sp_conf):
        # Use the frontend and context fixtures to dynamically create the
        # proxy IdP server that would be created during a flow.
        idp_server = frontend._create_co_virtual_idp(context)

        # Use the context fixture to find the CO name and the backend name
        # and then use those to dynamically update the ipd_conf fixture.
        co_name = frontend._get_co_name(context)
        backend_name = context.target_backend
        idp_conf = frontend._add_endpoints_to_config(idp_conf, co_name,
                                                     backend_name)
        idp_conf = frontend._add_entity_id(idp_conf, co_name)

        # Use a utility function to serialize the idp_conf IdP configuration
        # fixture to a string and then dynamically update the sp_conf
        # SP configuration fixture with the metadata.
        idp_metadata_str = create_metadata_from_config_dict(idp_conf)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        sp_config = SPConfig().load(sp_conf, metadata_construction=False)

        # Use the updated sp_config fixture to generate a fake SP and then
        # use the fake SP to generate an authentication request aimed at the
        # proxy CO virtual IdP.
        fakesp = FakeSP(sp_config)
        destination, auth_req = fakesp.make_auth_req(
            idp_server.config.entityid,
            nameid_format=None,
            relay_state="relay_state",
            subject=None,
        )

        # Update the context with the authentication request.
        context.request = auth_req

        # Create the response arguments necessary for the IdP to respond to
        # the authentication request, update the request state and with it
        # the context, and then use the frontend fixture and the
        # internal_response fixture to handle the authentication response
        # and generate a response from the proxy IdP to the SP.
        resp_args = {
            "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to": None,
            "destination": sp_config.endpoint(
                            "assertion_consumer_service",
                            binding=BINDING_HTTP_REDIRECT
                            )[0],
            "sp_entity_id": sp_conf["entityid"],
            "binding": BINDING_HTTP_REDIRECT
        }
        request_state = frontend._create_state_data(context, resp_args, "")
        context.state[frontend.name] = request_state
        frontend.handle_authn_response(context, internal_response)

        # Verify that the frontend added the CO static SAML attributes to the
        # internal response.
        for attr, value in self.CO_STATIC_SAML_ATTRIBUTES.items():
            assert internal_response.attributes[attr] == value
Ejemplo n.º 10
0
 def setup(self):
     """
     Initiates the test.
     :return: None
     """
     self.sp = FakeSP(None,
                      config=SPConfig().load(
                          TestConfiguration.get_instance().fake_sp_config,
                          metadata_construction=False))
     self.idp = FakeIdP(
         USERS,
         IdPConfig().load(TestConfiguration.get_instance().fake_idp_config,
                          metadata_construction=False))
Ejemplo n.º 11
0
    def test_handle_authn_request(self, context, idp_conf, sp_conf, internal_response):
        samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf)
        _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT)
        assert internal_req.requester == sp_conf["entityid"]

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        resp = fakesp.parse_authn_request_response(resp_dict["SAMLResponse"][0],
                                                   BINDING_HTTP_REDIRECT)
        for key in resp.ava:
            assert USERS["testuser1"][key] == resp.ava[key]
Ejemplo n.º 12
0
    def test_handle_authn_request(self, context, idp_conf, sp_conf, internal_response):
        samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf)
        _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT)
        assert internal_req.requester == sp_conf["entityid"]

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        resp = fakesp.parse_authn_request_response(resp_dict["SAMLResponse"][0],
                                                   BINDING_HTTP_REDIRECT)
        for key in resp.ava:
            assert USERS["testuser1"][key] == resp.ava[key]
Ejemplo n.º 13
0
    def test_acr_mapping_per_idp_in_authn_response(self, idp_conf, sp_conf):
        expected_loa = "LoA1"
        loa = {
            "": "http://eidas.europa.eu/LoA/low",
            idp_conf["entityid"]: expected_loa
        }

        base = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        conf = {
            "idp_config": idp_conf,
            "endpoints": ENDPOINTS,
            "base": base,
            "state_id": "state_id",
            "acr_mapping": loa
        }

        samlfrontend = SamlFrontend(None, INTERNAL_ATTRIBUTES, conf)
        samlfrontend.register_endpoints(["foo"])

        idp_metadata_str = create_metadata_from_config_dict(
            samlfrontend.config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        fakesp = FakeSP(None,
                        config=SPConfig().load(sp_conf,
                                               metadata_construction=False))

        auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z",
                                              idp_conf["entityid"])
        internal_response = InternalResponse(auth_info=auth_info)
        context = Context()
        context.state = State()

        resp_args = {
            "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to": None,
            "destination": "",
            "sp_entity_id": None,
            "binding": BINDING_HTTP_REDIRECT
        }
        request_state = samlfrontend.save_state(context, resp_args, "")
        context.state.add(conf["state_id"], request_state)

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)
        resp = fakesp.parse_authn_request_response(
            resp_dict['SAMLResponse'][0], BINDING_HTTP_REDIRECT)

        assert len(resp.assertion.authn_statement) == 1
        authn_context_class_ref = resp.assertion.authn_statement[
            0].authn_context.authn_context_class_ref
        assert authn_context_class_ref.text == expected_loa
Ejemplo n.º 14
0
    def run_test(self, satosa_config_dict, sp_conf, oidc_backend_config, frontend_config):
        subject_id = "testuser1"
        # proxy config
        satosa_config_dict["FRONTEND_MODULES"] = [frontend_config]
        satosa_config_dict["BACKEND_MODULES"] = [oidc_backend_config]
        satosa_config_dict["INTERNAL_ATTRIBUTES"]["attributes"] = {attr_name: {"openid": [attr_name],
                                                                               "saml": [attr_name]}
                                                                   for attr_name in USERS[subject_id]}
        frontend_metadata, backend_metadata = create_entity_descriptors(SATOSAConfig(satosa_config_dict))

        # application
        test_client = Client(make_app(SATOSAConfig(satosa_config_dict)), BaseResponse)

        # config test SP
        frontend_metadata_str = str(frontend_metadata[frontend_config["name"]][0])
        sp_conf["metadata"]["inline"].append(frontend_metadata_str)
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))

        # create auth req
        destination, req_args = fakesp.make_auth_req(frontend_metadata[frontend_config["name"]][0].entity_id)
        auth_req = urlparse(destination).path + "?" + urlencode(req_args)

        # make auth req to proxy
        proxied_auth_req = test_client.get(auth_req)
        assert proxied_auth_req.status == "302 Found"
        parsed_auth_req = dict(parse_qsl(urlparse(proxied_auth_req.data.decode("utf-8")).query))

        # create auth resp
        id_token_claims = {k: v[0] for k, v in USERS[subject_id].items()}
        id_token_claims["sub"] = subject_id
        id_token_claims["iat"] = time.time()
        id_token_claims["exp"] = time.time() + 3600
        id_token_claims["iss"] = "https://op.example.com"
        id_token_claims["aud"] = oidc_backend_config["config"]["client"]["client_metadata"]["client_id"]
        id_token_claims["nonce"] = parsed_auth_req["nonce"]
        id_token = IdToken(**id_token_claims).to_jwt()
        authn_resp = {"state": parsed_auth_req["state"], "id_token": id_token}

        # make auth resp to proxy
        redirect_uri_path = urlparse(
            oidc_backend_config["config"]["client"]["client_metadata"]["redirect_uris"][0]).path
        authn_resp_req = redirect_uri_path + "?" + urlencode(authn_resp)
        authn_resp = test_client.get(authn_resp_req)
        assert authn_resp.status == "303 See Other"

        # verify auth resp from proxy
        resp_dict = dict(parse_qsl(urlparse(authn_resp.data.decode("utf-8")).query))
        auth_resp = fakesp.parse_authn_request_response(resp_dict["SAMLResponse"], BINDING_HTTP_REDIRECT)
        assert auth_resp.ava == USERS[subject_id]
Ejemplo n.º 15
0
    def run_test(self, satosa_config_dict, sp_conf, idp_conf, saml_backend_config, frontend_config):
        user_id = "testuser1"
        # proxy config
        satosa_config_dict["FRONTEND_MODULES"] = [frontend_config]
        satosa_config_dict["BACKEND_MODULES"] = [saml_backend_config]
        satosa_config_dict["INTERNAL_ATTRIBUTES"]["attributes"] = {attr_name: {"saml": [attr_name]} for attr_name in
                                                                   USERS[user_id]}
        frontend_metadata, backend_metadata = create_entity_descriptors(SATOSAConfig(satosa_config_dict))

        # application
        test_client = Client(make_app(SATOSAConfig(satosa_config_dict)), BaseResponse)

        # config test SP
        frontend_metadata_str = str(frontend_metadata[frontend_config["name"]][0])
        sp_conf["metadata"]["inline"].append(frontend_metadata_str)
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))

        # create auth req
        destination, req_args = fakesp.make_auth_req(frontend_metadata[frontend_config["name"]][0].entity_id)
        auth_req = urlparse(destination).path + "?" + urlencode(req_args)

        # make auth req to proxy
        proxied_auth_req = test_client.get(auth_req)
        assert proxied_auth_req.status == "303 See Other"

        # config test IdP
        backend_metadata_str = str(backend_metadata[saml_backend_config["name"]][0])
        idp_conf["metadata"]["inline"].append(backend_metadata_str)
        fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf, metadata_construction=False))

        # create auth resp
        req_params = dict(parse_qsl(urlparse(proxied_auth_req.data.decode("utf-8")).query))
        url, authn_resp = fakeidp.handle_auth_req(
            req_params["SAMLRequest"],
            req_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            user_id,
            response_binding=BINDING_HTTP_REDIRECT)

        # make auth resp to proxy
        authn_resp_req = urlparse(url).path + "?" + urlencode(authn_resp)
        authn_resp = test_client.get("/" + authn_resp_req)
        assert authn_resp.status == "303 See Other"

        # verify auth resp from proxy
        resp_dict = dict(parse_qsl(urlparse(authn_resp.data.decode("utf-8")).query))
        auth_resp = fakesp.parse_authn_request_response(resp_dict["SAMLResponse"], BINDING_HTTP_REDIRECT)
        assert auth_resp.ava == USERS[user_id]
Ejemplo n.º 16
0
    def test_authn_response(self, context, idp_conf, sp_conf):
        response_binding = BINDING_HTTP_REDIRECT
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf, metadata_construction=False))
        destination, request_params = fakesp.make_auth_req(idp_conf["entityid"])
        url, auth_resp = fakeidp.handle_auth_req(request_params["SAMLRequest"], request_params["RelayState"],
                                                 BINDING_HTTP_REDIRECT,
                                                 "testuser1", response_binding=response_binding)

        context.request = auth_resp
        context.state[self.samlbackend.name] = {"relay_state": request_params["RelayState"]}
        self.samlbackend.authn_response(context, response_binding)

        context, internal_resp = self.samlbackend.auth_callback_func.call_args[0]
        self.assert_authn_response(internal_resp)
        assert self.samlbackend.name not in context.state
Ejemplo n.º 17
0
    def get_auth_response(self, samlfrontend, context, internal_response, sp_conf, idp_metadata_str):
        sp_config = SPConfig().load(sp_conf, metadata_construction=False)
        resp_args = {
            "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to": None,
            "destination": sp_config.endpoint("assertion_consumer_service", binding=BINDING_HTTP_REDIRECT)[0],
            "sp_entity_id": sp_conf["entityid"],
            "binding": BINDING_HTTP_REDIRECT
        }
        request_state = samlfrontend._create_state_data(context, resp_args, "")
        context.state[samlfrontend.name] = request_state

        resp = samlfrontend.handle_authn_response(context, internal_response)

        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        fakesp = FakeSP(sp_config)
        resp_dict = parse_qs(urlparse(resp.message).query)
        return fakesp.parse_authn_request_response(resp_dict["SAMLResponse"][0], BINDING_HTTP_REDIRECT)
Ejemplo n.º 18
0
 def setup(self):
     """
     Initiates the test.
     :return: None
     """
     self.sp = FakeSP(None, config=SPConfig().load(TestConfiguration.get_instance().
                                                   fake_sp_config,
                                                   metadata_construction=False))
     self.idp = FakeIdP(USERS, IdPConfig().load(TestConfiguration.get_instance().fake_idp_config,
                                                metadata_construction=False))
Ejemplo n.º 19
0
    def test_handle_authn_response_without_name_id(
                          self, context, idp_conf, sp_conf, internal_response):
        samlfrontend = self.setup_for_authn_req(
                                  context, idp_conf, sp_conf, relay_state=None)
        _, internal_req = samlfrontend.handle_authn_request(
                                                context, BINDING_HTTP_REDIRECT)

        # Make sure we are testing the equivalent of a <Response> with no
        # <NameID> in the <Subject>.
        assert internal_response.subject_type is None
        assert internal_response.subject_id is None

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        resp = fakesp.parse_authn_request_response(
                           resp_dict["SAMLResponse"][0], BINDING_HTTP_REDIRECT)

        # The <NameID> must not have an empty TextContent.
        assert resp.name_id.text is not None
Ejemplo n.º 20
0
    def test_handle_authn_response_without_name_id(
                          self, context, idp_conf, sp_conf, internal_response):
        samlfrontend = self.setup_for_authn_req(
                                  context, idp_conf, sp_conf, relay_state=None)
        _, internal_req = samlfrontend.handle_authn_request(
                                                context, BINDING_HTTP_REDIRECT)

        # Make sure we are testing the equivalent of a <Response> with no
        # <NameID> in the <Subject>.
        assert internal_response.subject_type is None
        assert internal_response.subject_id is None

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))
        resp = fakesp.parse_authn_request_response(
                           resp_dict["SAMLResponse"][0], BINDING_HTTP_REDIRECT)

        # The <NameID> must not have an empty TextContent.
        assert resp.name_id.text is not None
Ejemplo n.º 21
0
    def test_handle_authn_request_without_name_id_policy(self, idp_conf, sp_conf):
        """
        Performs a complete test for the module. The flow should be accepted.
        """
        context, samlfrontend = self.setup_for_authn_req(idp_conf, sp_conf, "")
        _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT)
        assert internal_req.requestor == sp_conf["entityid"]

        auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", "unittest_idp.xml")
        internal_response = InternalResponse(auth_info=auth_info)
        internal_response.set_user_id_hash_type(internal_req.user_id_hash_type)
        internal_response.add_attributes(USERS["testuser1"])

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False))
        resp = fakesp.parse_authn_request_response(resp_dict['SAMLResponse'][0],
                                                   BINDING_HTTP_REDIRECT)
        for key in resp.ava:
            assert USERS["testuser1"][key] == resp.ava[key]
Ejemplo n.º 22
0
    def test_acr_mapping_per_idp_in_authn_response(self, idp_conf, sp_conf):
        expected_loa = "LoA1"
        loa = {"": "http://eidas.europa.eu/LoA/low", idp_conf["entityid"]: expected_loa}

        base = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        conf = {"idp_config": idp_conf, "endpoints": ENDPOINTS, "base": base,
                "state_id": "state_id", "acr_mapping": loa}

        samlfrontend = SamlFrontend(None, INTERNAL_ATTRIBUTES, conf)
        samlfrontend.register_endpoints(["foo"])

        idp_metadata_str = create_metadata_from_config_dict(samlfrontend.config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False))

        auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"])
        internal_response = InternalResponse(auth_info=auth_info)
        context = Context()
        context.state = State()

        resp_args = {
            "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to": None,
            "destination": "",
            "sp_entity_id": None,
            "binding": BINDING_HTTP_REDIRECT

        }
        request_state = samlfrontend.save_state(context, resp_args, "")
        context.state.add(conf["state_id"], request_state)

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)
        resp = fakesp.parse_authn_request_response(resp_dict['SAMLResponse'][0],
                                                   BINDING_HTTP_REDIRECT)

        assert len(resp.assertion.authn_statement) == 1
        authn_context_class_ref = resp.assertion.authn_statement[
            0].authn_context.authn_context_class_ref
        assert authn_context_class_ref.text == expected_loa
Ejemplo n.º 23
0
    def test_respect_sp_entity_categories(self, entity_category, expected_attributes, idp_conf, sp_conf):
        base = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        conf = {"idp_config": idp_conf, "endpoints": ENDPOINTS, "base": base,
                "state_id": "state_id"}

        internal_attributes = {attr_name: {"saml": [attr_name.lower()]} for attr_name in expected_attributes}
        samlfrontend = SamlFrontend(None, dict(attributes=internal_attributes), conf)
        samlfrontend.register_endpoints(["foo"])

        idp_metadata_str = create_metadata_from_config_dict(samlfrontend.idp_config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)
        sp_conf["entity_category"] = entity_category
        fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False))

        auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"])
        internal_response = InternalResponse(auth_info=auth_info)

        user_attributes = {k: "foo" for k in expected_attributes}
        user_attributes.update({k: "bar" for k in ["extra", "more", "stuff"]})
        internal_response.add_attributes(user_attributes)
        context = Context()
        context.state = State()

        resp_args = {
            "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT),
            "in_response_to": None,
            "destination": "",
            "sp_entity_id": None,
            "binding": BINDING_HTTP_REDIRECT
        }
        request_state = samlfrontend.save_state(context, resp_args, "")
        context.state.add(conf["state_id"], request_state)

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)
        resp = fakesp.parse_authn_request_response(resp_dict['SAMLResponse'][0],
                                                   BINDING_HTTP_REDIRECT)

        assert Counter(resp.ava.keys()) == Counter(expected_attributes)
Ejemplo n.º 24
0
    def test_handle_authn_response_without_relay_state(self, context, idp_conf,
                                                       sp_conf,
                                                       internal_response):
        samlfrontend = self.setup_for_authn_req(context,
                                                idp_conf,
                                                sp_conf,
                                                relay_state=None)
        _, internal_req = samlfrontend.handle_authn_request(
            context, BINDING_HTTP_REDIRECT)
        assert internal_req.requester == sp_conf["entityid"]

        resp = samlfrontend.handle_authn_response(context, internal_response)
        resp_dict = parse_qs(urlparse(resp.message).query)

        fakesp = FakeSP(SPConfig().load(sp_conf))
        resp = fakesp.parse_authn_request_response(
            resp_dict["SAMLResponse"][0], BINDING_HTTP_REDIRECT)

        for key in resp.ava:
            assert USERS["testuser1"][key] == resp.ava[key]

        assert samlfrontend.name not in context.state
Ejemplo n.º 25
0
    def setup_for_authn_req(self, idp_conf, sp_conf, nameid_format):
        base = self.construct_base_url_from_entity_id(idp_conf["entityid"])
        config = {
            "idp_config": idp_conf,
            "endpoints": ENDPOINTS,
            "base": base,
            "state_id": "state_id"
        }
        sp_metadata_str = create_metadata_from_config_dict(sp_conf)
        idp_conf["metadata"]["inline"] = [sp_metadata_str]

        samlfrontend = SamlFrontend(
            lambda context, internal_req: (context, internal_req),
            INTERNAL_ATTRIBUTES, config)
        samlfrontend.register_endpoints(["saml"])

        idp_metadata_str = create_metadata_from_config_dict(
            samlfrontend.config)
        sp_conf["metadata"]["inline"].append(idp_metadata_str)

        fakesp = FakeSP(None,
                        config=SPConfig().load(sp_conf,
                                               metadata_construction=False))
        context = Context()
        context.state = State()
        context.request = parse.parse_qs(
            urlparse(
                fakesp.make_auth_req(samlfrontend.config["entityid"],
                                     nameid_format)).query)
        tmp_dict = {}
        for val in context.request:
            if isinstance(context.request[val], list):
                tmp_dict[val] = context.request[val][0]
            else:
                tmp_dict[val] = context.request[val]
        context.request = tmp_dict

        return context, samlfrontend
Ejemplo n.º 26
0
class TestProxy:
    """
    Performs a complete flow test for the proxy.
    Verifies SAML -> PROXY -> SAML.
    """
    @pytest.fixture(autouse=True)
    def setup(self):
        """
        Initiates the test.
        :return: None
        """
        self.sp = FakeSP(None,
                         config=SPConfig().load(
                             TestConfiguration.get_instance().fake_sp_config,
                             metadata_construction=False))
        self.idp = FakeIdP(
            USERS,
            IdPConfig().load(TestConfiguration.get_instance().fake_idp_config,
                             metadata_construction=False))

    def test_flow(self):
        """
        Performs the test.
        """
        e_id = 'https://localhost:8090/proxy.xml'
        target_id = 'https://example.com/unittest_idp.xml'
        url = "{}&entityID={}".format(self.sp.make_auth_req(e_id),
                                      quote(target_id))

        app = WsgiApplication(
            config=TestConfiguration.get_instance().proxy_config)
        test_client = Client(app.run_server, BaseResponse)

        parsed = urlparse(url)
        request = "{}?{}".format(parsed.path, parsed.query)

        resp = test_client.get(request)
        assert resp.status == '303 See Other'
        headers = dict(resp.headers)
        assert headers["Set-Cookie"], "Did not save state in cookie!"

        url = headers["location"]
        req = parse_qs(urlsplit(url).query)
        assert 'SAMLRequest' in req
        assert 'RelayState' in req

        action, body = self.idp.handle_auth_req(req['SAMLRequest'][0],
                                                req['RelayState'][0],
                                                BINDING_HTTP_REDIRECT,
                                                'testuser1')

        parsed = urlparse(action)
        request = "{}?{}".format(parsed.path, parsed.query)
        resp = test_client.post(request,
                                data=urlencode(body),
                                headers=[("Cookie", headers["Set-Cookie"]),
                                         ("Content-Type",
                                          "application/x-www-form-urlencoded")
                                         ])
        assert resp.status == '302 Found'

        headers = dict(resp.headers)
        url = headers["location"]
        req = parse_qs(urlsplit(url).query)
        assert 'SAMLResponse' in req
        assert 'RelayState' in req
        resp = self.sp.parse_authn_request_response(req['SAMLResponse'][0],
                                                    BINDING_HTTP_REDIRECT)

        identity = resp.ava
        assert identity["displayName"][0] == "Test Testsson"
Ejemplo n.º 27
0
class TestProxy:
    """
    Performs a complete flow test for the proxy.
    Verifies SAML -> PROXY -> SAML.
    """

    @pytest.fixture(autouse=True)
    def setup(self):
        """
        Initiates the test.
        :return: None
        """
        self.sp = FakeSP(None, config=SPConfig().load(TestConfiguration.get_instance().
                                                      fake_sp_config,
                                                      metadata_construction=False))
        self.idp = FakeIdP(USERS, IdPConfig().load(TestConfiguration.get_instance().fake_idp_config,
                                                   metadata_construction=False))

    def test_flow(self):
        """
        Performs the test.
        """
        e_id = 'https://localhost:8090/proxy.xml'
        target_id = 'https://example.com/unittest_idp.xml'
        url = "{}&entityID={}".format(self.sp.make_auth_req(e_id), quote(target_id))

        app = WsgiApplication(config=TestConfiguration.get_instance().proxy_config)
        test_client = Client(app.run_server, BaseResponse)

        parsed = urlparse(url)
        request = "{}?{}".format(parsed.path, parsed.query)

        resp = test_client.get(request)
        assert resp.status == '303 See Other'
        headers = dict(resp.headers)
        assert headers["Set-Cookie"], "Did not save state in cookie!"

        url = headers["location"]
        req = parse_qs(urlsplit(url).query)
        assert 'SAMLRequest' in req
        assert 'RelayState' in req

        action, body = self.idp.handle_auth_req(req['SAMLRequest'][0],
                                                req['RelayState'][0],
                                                BINDING_HTTP_REDIRECT,
                                                'testuser1')

        parsed = urlparse(action)
        request = "{}?{}".format(parsed.path, parsed.query)
        resp = test_client.post(request, data=urlencode(body),
                                headers=[("Cookie", headers["Set-Cookie"]),
                                         ("Content-Type", "application/x-www-form-urlencoded")])
        assert resp.status == '302 Found'

        headers = dict(resp.headers)
        url = headers["location"]
        req = parse_qs(urlsplit(url).query)
        assert 'SAMLResponse' in req
        assert 'RelayState' in req
        resp = self.sp.parse_authn_request_response(req['SAMLResponse'][0], BINDING_HTTP_REDIRECT)

        identity = resp.ava
        assert identity["displayName"][0] == "Test Testsson"
Ejemplo n.º 28
0
    def run_test(self, satosa_config_dict, sp_conf, idp_conf,
                 saml_backend_config, frontend_config):
        subject_id = "testuser1"
        # proxy config
        satosa_config_dict["FRONTEND_MODULES"] = [frontend_config]
        satosa_config_dict["BACKEND_MODULES"] = [saml_backend_config]
        satosa_config_dict["INTERNAL_ATTRIBUTES"]["attributes"] = {
            attr_name: {
                "saml": [attr_name]
            }
            for attr_name in USERS[subject_id]
        }
        frontend_metadata, backend_metadata = create_entity_descriptors(
            SATOSAConfig(satosa_config_dict))

        # application
        test_client = Client(make_app(SATOSAConfig(satosa_config_dict)),
                             BaseResponse)

        # config test SP
        frontend_metadata_str = str(
            frontend_metadata[frontend_config["name"]][0])
        sp_conf["metadata"]["inline"].append(frontend_metadata_str)
        fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False))

        # create auth req
        destination, req_args = fakesp.make_auth_req(
            frontend_metadata[frontend_config["name"]][0].entity_id)
        auth_req = urlparse(destination).path + "?" + urlencode(req_args)

        # make auth req to proxy
        proxied_auth_req = test_client.get(auth_req)
        assert proxied_auth_req.status == "303 See Other"

        # config test IdP
        backend_metadata_str = str(
            backend_metadata[saml_backend_config["name"]][0])
        idp_conf["metadata"]["inline"].append(backend_metadata_str)
        fakeidp = FakeIdP(USERS,
                          config=IdPConfig().load(idp_conf,
                                                  metadata_construction=False))

        # create auth resp
        req_params = dict(
            parse_qsl(urlparse(proxied_auth_req.data.decode("utf-8")).query))
        url, authn_resp = fakeidp.handle_auth_req(
            req_params["SAMLRequest"],
            req_params["RelayState"],
            BINDING_HTTP_REDIRECT,
            subject_id,
            response_binding=BINDING_HTTP_REDIRECT)

        # make auth resp to proxy
        authn_resp_req = urlparse(url).path + "?" + urlencode(authn_resp)
        authn_resp = test_client.get("/" + authn_resp_req)
        assert authn_resp.status == "303 See Other"

        # verify auth resp from proxy
        resp_dict = dict(
            parse_qsl(urlparse(authn_resp.data.decode("utf-8")).query))
        auth_resp = fakesp.parse_authn_request_response(
            resp_dict["SAMLResponse"], BINDING_HTTP_REDIRECT)
        assert auth_resp.ava == USERS[subject_id]