def testLogoutNoSLO(self):
        """
        Tests the logout method of the OneLogin_Saml2_Auth class
        Case IdP no SLO endpoint.
        """
        settings_info = self.loadSettingsJSON()
        del settings_info['idp']['singleLogoutService']
        auth = OneLogin_Saml2_Auth(self.get_request(),
                                   old_settings=settings_info)

        with self.assertRaisesRegexp(
                OneLogin_Saml2_Error,
                'The IdP does not support Single Log Out'):
            # The Header of the redirect produces an Exception
            auth.logout('http://example.com/returnto')
Exemple #2
0
    def testBuildRequestSignature(self):
        """
        Tests the build_request_signature method of the OneLogin_Saml2_Auth
        """
        settings = self.loadSettingsJSON()
        message = self.file_contents(
            join(self.data_path, 'logout_requests',
                 'logout_request_deflated.xml.base64'))
        relay_state = 'http://relaystate.com'
        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)

        signature = auth.build_request_signature(message, relay_state)
        valid_signature = 'Pb1EXAX5TyipSJ1SndEKZstLQTsT+1D00IZAhEepBM+OkAZQSToivu3njgJu47HZiZAqgXZFgloBuuWE/+GdcSsRYEMkEkiSDWTpUr25zKYLJDSg6GNo6iAHsKSuFt46Z54Xe/keYxYP03Hdy97EwuuSjBzzgRc5tmpV+KC7+a0='
        self.assertEqual(signature, valid_signature)

        settings['sp']['privatekey'] = ''
        settings['custom_base_path'] = u'invalid/path/'
        auth2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)
        try:
            auth2.build_request_signature(message, relay_state)
        except Exception as e:
            self.assertIn(
                "Trying to sign the SAMLRequest but can't load the SP private key",
                e.message)
Exemple #3
0
    def testBuildResponseSignature(self):
        """
        Tests the build_response_signature method of the OneLogin_Saml2_Auth
        """
        settings = self.loadSettingsJSON()
        message = self.file_contents(
            join(self.data_path, 'logout_responses',
                 'logout_response_deflated.xml.base64'))
        relay_state = 'http://relaystate.com'
        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)

        signature = auth.build_response_signature(message, relay_state)
        valid_signature = 'IcyWLRX6Dz3wHBfpcUaNLVDMGM3uo6z2Z11Gjq0/APPJaHboKGljffsgMVAGBml497yckq+eYKmmz+jpURV9yTj2sF9qfD6CwX2dEzSzMdRzB40X7pWyHgEJGIhs6BhaOt5oXEk4T+h3AczERqpVYFpL00yo7FNtyQkhZFpHFhM='
        self.assertEqual(signature, valid_signature)

        settings['sp']['privatekey'] = ''
        settings['custom_base_path'] = u'invalid/path/'
        auth2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)
        try:
            auth2.build_response_signature(message, relay_state)
        except Exception as e:
            self.assertIn(
                "Trying to sign the SAMLResponse but can't load the SP private key",
                e.message)
Exemple #4
0
async def saml_login(request: Request):
    req = await prepare_from_fastapi_request(request)
    auth = OneLogin_Saml2_Auth(req, saml_settings)
    # saml_settings = auth.get_settings()
    # metadata = saml_settings.get_sp_metadata()
    # errors = saml_settings.validate_metadata(metadata)
    # if len(errors) == 0:
    #   print(metadata)
    #   return metadata
    # else:
    #   print("Error found on Metadata: %s" % (', '.join(errors)))
    #   return "error"
    callback_url = auth.login()
    response = RedirectResponse(url=callback_url)
    return response
Exemple #5
0
    def testBuildRequestSignature(self):
        """
        Tests the build_request_signature method of the OneLogin_Saml2_Auth
        """
        settings = self.loadSettingsJSON()
        message = self.file_contents(
            join(self.data_path, 'logout_requests',
                 'logout_request_deflated.xml.base64'))
        relay_state = 'http://relaystate.com'
        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)

        signature = auth.build_request_signature(message, relay_state)
        valid_signature = 'E17GU1STzanOXxBTKjweB1DovP8aMJdj5BEy0fnGoEslKdP6hpPc3enjT/bu7I8D8QzLoir8SxZVWdUDXgIxJIEgfK5snr+jJwfc5U2HujsOa/Xb3c4swoyPcyQhcxLRDhDjPq5cQxJfYoPeElvCuI6HAD1mtdd5PS/xDvbIxuw='
        self.assertEqual(signature, valid_signature)

        settings['sp']['privatekey'] = ''
        settings['custom_base_path'] = u'invalid/path/'
        auth2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings)
        try:
            auth2.build_request_signature(message, relay_state)
        except Exception as e:
            self.assertIn(
                "Trying to sign the SAMLRequest but can't load the SP private key",
                e.message)
Exemple #6
0
    def POST(self):

        if not EXTRA_MODULES['onelogin']:
            header('X-Rucio-Auth-Token', None)
            return "SAML not configured on the server side."

        SAML_PATH = config_get('saml', 'config_path')
        req = prepare_saml_request(ctx.env, dict(param_input()))
        auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH)

        auth.process_response()
        errors = auth.get_errors()
        if not errors:
            if auth.is_authenticated():
                setcookie('saml-nameid', value=auth.get_nameid(), path='/')
Exemple #7
0
def build_auth(request, saml_config):
    """
    Construct a OneLogin_Saml2_Auth object for the current request.
    """
    url = urlparse(options.get("system.url-prefix"))
    saml_request = {
        "https": "on" if url.scheme == "https" else "off",
        "http_host": url.hostname,
        "script_name": request.META["PATH_INFO"],
        "server_port": url.port,
        "get_data": request.GET.copy(),
        "post_data": request.POST.copy(),
    }

    return OneLogin_Saml2_Auth(saml_request, saml_config)
Exemple #8
0
    def testLogoutNoSLO(self):
        """
        Tests the logout method of the OneLogin_Saml2_Auth class
        Case IdP no SLO endpoint.
        """
        settings_info = self.loadSettingsJSON()
        del settings_info['idp']['singleLogoutService']
        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)

        try:
            # The Header of the redirect produces an Exception
            auth.logout('http://example.com/returnto')
            self.assertFalse(True)
        except Exception as e:
            self.assertIn('The IdP does not support Single Log Out', e.message)
Exemple #9
0
    def testProcessNoResponse(self):
        """
        Tests the process_response method of the OneLogin_Saml2_Auth class
        Case No Response, An exception is throw
        """
        auth = OneLogin_Saml2_Auth(self.get_request(),
                                   old_settings=self.loadSettingsJSON())

        try:
            auth.process_response()
            self.assertFalse(True)
        except Exception as e:
            self.assertIn('SAML Response not found', e.message)

        self.assertEqual(auth.get_errors(), ['invalid_binding'])
Exemple #10
0
def build_auth(request, saml_config):
    """
    Construct a OneLogin_Saml2_Auth object for the current request.
    """
    url = urlparse(options.get('system.url-prefix'))
    saml_request = {
        'https': 'on' if url.scheme == 'https' else 'off',
        'http_host': url.hostname,
        'script_name': request.META['PATH_INFO'],
        'server_port': url.port,
        'get_data': request.GET.copy(),
        'post_data': request.POST.copy()
    }

    return OneLogin_Saml2_Auth(saml_request, saml_config)
Exemple #11
0
    def wrapper():
        app = flask.current_app
        saml_app_extension = app.extensions.setdefault('saml', {})
        saml_settings = saml_app_extension.get(key)
        if not saml_settings:
            settings_dict = settings.get_saml_settings(app, idp=idp_enabled)
            saml_settings = OneLogin_Saml2_Settings(
                settings_dict, sp_validation_only=not idp_enabled)
            saml_app_extension[key] = saml_settings
            logger.debug('SAML Metadata Settings ({}): \n{}'.format(
                key, settings_dict))

        req = _prepare_flask_request(app.config)
        auth = OneLogin_Saml2_Auth(req, saml_settings)
        return func(auth)
Exemple #12
0
 def testRedirectTowithUrl(self):
     """
     Tests the redirect_to method of the OneLogin_Saml2_Auth class
     (phpunit raises an exception when a redirect is executed, the
     exception is catched and we check that the targetURL is correct)
     Case redirect with url parameter
     """
     request_data = self.get_request()
     relay_state = 'http://sp.example.com'
     url_2 = 'http://sp2.example.com'
     request_data['get_data']['RelayState'] = relay_state
     auth = OneLogin_Saml2_Auth(request_data,
                                old_settings=self.loadSettingsJSON())
     target_url = auth.redirect_to(url_2)
     self.assertEqual(target_url, url_2)
Exemple #13
0
    def post(self):
        if "onelogin" not in current_app.config.get("ACTIVE_PROVIDERS"):
            return "Onelogin is not enabled in the config.  See the ACTIVE_PROVIDERS section.", 404
        auth = OneLogin_Saml2_Auth(self.req, current_app.config.get("ONELOGIN_SETTINGS"))

        self.reqparse.add_argument('return_to', required=False, default=current_app.config.get('WEB_PATH'))
        self.reqparse.add_argument('acs', required=False)
        self.reqparse.add_argument('sls', required=False)

        args = self.reqparse.parse_args()

        return_to = args['return_to']

        if args['acs'] != None:
            # valids the SAML response and checks if successfully authenticated
            if self._consumer(auth):
                email = auth.get_attribute(current_app.config.get("ONELOGIN_EMAIL_FIELD"))[0]
                user = User.query.filter(User.email == email).first()

                # if we get an sso user create them an account
                if not user:
                    user = User(
                        email=email,
                        active=True,
                        role=current_app.config.get('ONELOGIN_DEFAULT_ROLE')
                        # profile_picture=profile.get('thumbnailPhotoUrl')
                    )
                    db.session.add(user)
                    db.session.commit()
                    db.session.refresh(user)

                # Tell Flask-Principal the identity changed
                identity_changed.send(current_app._get_current_object(), identity=Identity(user.id))
                login_user(user)
                db.session.commit()
                db.session.refresh(user)

                self_url = OneLogin_Saml2_Utils.get_self_url(self.req)
                if 'RelayState' in request.form and self_url != request.form['RelayState']:
                    return redirect(auth.redirect_to(request.form['RelayState']), code=302)
                else:
                    return redirect(current_app.config.get('BASE_URL'), code=302)
            else:
                return dict(message='OneLogin authentication failed.'), 403
        elif args['sls'] != None:
            return dict(message='OneLogin SLS not implemented yet.'), 405
        else:
            return redirect(auth.login(return_to=return_to))
Exemple #14
0
def acs(request, idp_slug):
    idp = get_object_or_404(IdP, slug=idp_slug, is_active=True)
    if request.POST.get("RelayState"):
        # Login with state relayed from our application.
        state = signing.loads(request.POST["RelayState"], max_age=300)
    else:
        # IdP-initiated login.
        state = {"test": False, "verify": False, "redir": ""}
    saml = OneLogin_Saml2_Auth(idp.prepare_request(request), old_settings=idp.settings)
    saml.process_response()
    errors = saml.get_errors()
    if errors:
        return render(
            request,
            "sp/error.html",
            {"idp": idp, "state": state, "errors": errors, "reason": saml.get_last_error_reason()},
            status=500,
        )
    else:
        if state.get("test", False):
            attrs = []
            for saml_attr, value in saml.get_attributes().items():
                attr, created = idp.attributes.get_or_create(saml_attribute=saml_attr)
                attrs.append((attr, "; ".join(value)))
            return render(
                request,
                "sp/test.html",
                {"idp": idp, "attrs": attrs, "nameid": saml.get_nameid(), "nameid_format": saml.get_nameid_format()},
            )
        elif state.get("verify", False):
            user = idp.authenticate(request, saml)
            if user == request.user:
                return redirect(idp.get_login_redirect(state.get("redir")))
            else:
                return render(
                    request, "sp/unauth.html", {"nameid": idp.get_nameid(saml), "idp": idp, "verify": True}, status=401
                )
        else:
            user = idp.authenticate(request, saml)
            if user:
                idp.login(request, user, saml)
                idp.last_login = timezone.now()
                idp.save(update_fields=("last_login",))
                return redirect(idp.get_login_redirect(state.get("redir")))
            else:
                return render(
                    request, "sp/unauth.html", {"nameid": idp.get_nameid(saml), "idp": idp, "verify": False}, status=401
                )
def init_saml_auth(req, saml_path):
    """
    Init SAML authentication for remote application.

    Args:
        req(dict):
        saml_path(str): The path to the configuration files for python3-saml.

    Returns:

    """
    auth = OneLogin_Saml2_Auth(
        req,
        custom_base_path=saml_path
    )
    return auth
Exemple #16
0
 def get_saml_auth(self, request):
     saml_request = dict(SamlSettings.get_request_settings())
     # Update not existing keys
     saml_request['https'] = saml_request.get(
         'https', 'on' if request.is_secure() else 'off')
     saml_request['http_host'] = saml_request.get('http_host',
                                                  request.META['HTTP_HOST'])
     saml_request['script_name'] = saml_request.get(
         'script_name', request.META['PATH_INFO'])
     saml_request['server_port'] = saml_request.get(
         'server_port', request.META['SERVER_PORT'])
     # add get and post data
     saml_request['get_data'] = request.GET.copy()
     saml_request['post_data'] = request.POST.copy()
     return saml_request, OneLogin_Saml2_Auth(saml_request,
                                              SamlSettings.get())
def logout(request):
    """Kick off a SAML logout request."""
    req = prepare_django_request(request)
    saml_auth = OneLogin_Saml2_Auth(req, old_settings=settings.ONELOGIN_SAML_SETTINGS)
    name_id = request.session.get('samlNameId', None)
    session_index = request.session.get('samlSessionIndex', None)
    name_id_format = request.session.get('samlNameIdFormat', None)
    name_id_nq = request.session.get('samlNameIdNameQualifier', None)
    name_id_spnq = request.session.get('samlNameIdSPNameQualifier', None)
    auth.logout(request)
    url = saml_auth.logout(
        name_id=name_id, session_index=session_index, nq=name_id_nq, name_id_format=name_id_format, spnq=name_id_spnq,
        return_to=OneLogin_Saml2_Utils.get_self_url(req) + settings.SAML_LOGOUT_REDIRECT
    )
    request.session['LogoutRequestID'] = saml_auth.get_last_request_id()
    return HttpResponseRedirect(url)
Exemple #18
0
def login(request, test=False, verify=False, **kwargs):
    idp = get_request_idp(request, **kwargs)
    saml = OneLogin_Saml2_Auth(idp.prepare_request(request),
                               old_settings=idp.settings)
    reauth = verify or "reauth" in request.GET
    state = signing.dumps({
        "test": test,
        "verify": verify,
        "redir": request.GET.get(REDIRECT_FIELD_NAME, ""),
    })
    # When verifying, we want to pass the (unmapped) SAML nameid, stored in the session.
    # TODO: do we actually want UPN here, or some other specified mapped field? At least
    # Auth0 is pre-populating the email field with nameid, which is not what we want.
    nameid = get_session_nameid(request) if verify else None
    return redirect(
        saml.login(state, force_authn=reauth, name_id_value_req=nameid))
Exemple #19
0
def init_saml_auth(req):
    # load based on production information.
    saml_dir = os.path.abspath(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), '..',
                     'saml'))
    saml_file = os.path.join(saml_dir, settings.SAML_SETTINGS)

    json_data_file = open(saml_file, 'r')
    settings_data = json.load(json_data_file)
    json_data_file.close()

    # create auth object with required settings.
    auth = OneLogin_Saml2_Auth(req, settings_data)

    # return it
    return auth, settings_data
Exemple #20
0
    def _saml_auth(self, req_dict=None):
        """
        Instantiate a OneLogin_Saml2_Auth object from the current request data
        (or from req_dict, if given).

        :param req_dict: A dict containing request information, optional.
        :type req_dict: dict

        :returns: a SAML Auth object
        :rtype: onelogin.saml2.auth.OneLogin_Saml2_Auth
        """
        if req_dict is None:
            req_dict = self._saml_req_dict_from_request()

        auth = OneLogin_Saml2_Auth(req_dict, self.saml_config)
        return auth
Exemple #21
0
def init_saml_auth():
    parsed_url = urlparse(request.url)
    request_data = {
        "https": "on" if request.scheme == "https" else "off",
        "http_host": request.host,
        "server_port": parsed_url.port,
        "script_name": request.path,
        "get_data": request.args.copy(),
        "post_data": request.form.copy(),
        "query_string": request.query_string
    }

    auth = OneLogin_Saml2_Auth(
        request_data,
        custom_base_path=get_env("INFRABOX_ACCOUNT_SAML_SETTINGS_PATH"))
    return auth
Exemple #22
0
    def _init_saml_request(self):
        tmpl = get_template('saml_settings.json')
        config = tmpl.render(
            strict=str(self.dbconfig.get('strict', self.ns, True)).lower(),
            debug=str(self.dbconfig.get('debug', self.ns, False)).lower(),
            sp_entity_id=self.dbconfig.get('sp_entity_id', self.ns),
            sp_acs=self.dbconfig.get('sp_acs', self.ns),
            sp_sls=self.dbconfig.get('sp_sls', self.ns),
            idp_entity_id=self.dbconfig.get('idp_entity_id', self.ns),
            idp_ssos=self.dbconfig.get('idp_ssos', self.ns),
            idp_sls=self.dbconfig.get('idp_sls', self.ns),
            idp_x509cert=self.dbconfig.get('idp_x509cert', self.ns)
        )

        auth = OneLogin_Saml2_Auth(self.req, json.loads(config))
        auth.set_strict(False)
        return auth
Exemple #23
0
    def testGetLastErrorReason(self):
        """
        Tests the get_last_error_reason method of the OneLogin_Saml2_Auth class
        Case Invalid Response
        """
        request_data = self.get_request()
        message = self.file_contents(
            join(self.data_path, 'responses', 'response1.xml.base64'))
        del request_data['get_data']
        request_data['post_data'] = {'SAMLResponse': message}
        auth = OneLogin_Saml2_Auth(request_data,
                                   old_settings=self.loadSettingsJSON())
        auth.process_response()

        self.assertEqual(
            auth.get_last_error_reason(),
            'Signature validation failed. SAML Response rejected')
Exemple #24
0
def _prepare_saml_auth(request):
    saml_setting = OneLogin_Saml2_Settings(
        custom_base_path=settings.SAML_FOLDER)
    metadata = saml_setting.get_sp_data()
    saml_server_url = metadata['assertionConsumerService']['url']
    parsed_saml_server_url = urlparse(saml_server_url)
    req = {
        'https': 'on' if parsed_saml_server_url.scheme == 'https' else 'off',
        'http_host': parsed_saml_server_url.hostname,
        'script_name': parsed_saml_server_url.path.split('/')[0],
        'server_port': parsed_saml_server_url.port,
        'get_data': request.GET.copy(),
        'lowercase_urlencoding': True,
        'post_data': request.POST.copy(),
    }
    auth = OneLogin_Saml2_Auth(req, custom_base_path=settings.SAML_FOLDER)
    return auth
Exemple #25
0
    def _create_auth_object(self, db, idp_entity_id):
        """Creates and initializes an OneLogin_Saml2_Auth object

        :param db: Database session
        :type db: sqlalchemy.orm.session.Session

        :param idp_entity_id: IdP's entityID
        :type idp_entity_id: string

        :return: OneLogin_Saml2_Auth object
        :rtype: OneLogin_Saml2_Auth
        """
        request_data = self._get_request_data()
        settings = self._configuration.get_settings(db, idp_entity_id)
        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings)

        return auth
Exemple #26
0
    def testProcessSLORequestDeletingSession(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Valid Logout Request, validating that the local session is deleted,
        a LogoutResponse is created and a redirection executed
        """
        settings_info = self.loadSettingsJSON()
        request_data = self.get_request()
        message = self.file_contents(
            join(self.data_path, 'logout_requests',
                 'logout_request_deflated.xml.base64'))
        # In order to avoid the destination problem
        plain_message = OneLogin_Saml2_Utils.decode_base64_and_inflate(message)
        current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data)
        plain_message = plain_message.replace(
            'http://stuff.com/endpoints/endpoints/sls.php', current_url)
        message = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message)
        request_data['get_data']['SAMLRequest'] = message
        # FIXME
        # if (!isset($_SESSION)) {
        #     $_SESSION = array();
        # }
        # $_SESSION['samltest'] = true;
        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info)

        auth.set_strict(True)
        target_url = auth.process_slo(True)
        parsed_query = parse_qs(urlparse(target_url)[4])
        slo_url = settings_info['idp']['singleLogoutService']['url']
        self.assertIn(slo_url, target_url)
        self.assertIn('SAMLResponse', parsed_query)
        self.assertNotIn('RelayState', parsed_query)

        # FIXME // Session is not alive
        # $this->assertFalse(isset($_SESSION['samltest']));

        # $_SESSION['samltest'] = true;

        auth.set_strict(True)
        target_url_2 = auth.process_slo(True)
        target_url_2 = auth.process_slo(True)
        parsed_query_2 = parse_qs(urlparse(target_url_2)[4])
        slo_url = settings_info['idp']['singleLogoutService']['url']
        self.assertIn(slo_url, target_url_2)
        self.assertIn('SAMLResponse', parsed_query_2)
        self.assertNotIn('RelayState', parsed_query_2)
Exemple #27
0
    def _create_saml_auth(self, idp, remove_signature_from_get=False):
        """ Добавляет возможность удалить 'Signature' из параметров,
            https://github.com/wfmexpert/wfmportal/issues/1111 """
        get_data = self.strategy.request_get()
        if remove_signature_from_get:
            get_data.pop('Signature', None)

        config = self.generate_saml_config(idp)
        request_info = {
            'https': 'on' if self.strategy.request_is_secure() else 'off',
            'http_host': self.strategy.request_host(),
            'script_name': self.strategy.request_path(),
            'server_port': self.strategy.request_port(),
            'get_data': get_data,
            'post_data': self.strategy.request_post(),
        }
        return OneLogin_Saml2_Auth(request_info, config)
Exemple #28
0
def prepare_auth_request(request, saml_config):
    """Helper function to prepare authenitcation request.
    """
    if settings.DEBUG:
        server_port = '5050'
    else:
        server_port = '443'

    saml_request = {
        'https': 'on' if request.is_secure() else 'off',
        'http_host': request.META['HTTP_HOST'],
        'script_name': request.META['PATH_INFO'],
        'server_port': server_port,
        'get_data': request.GET.copy(),
        'post_data': request.POST.copy()
    }
    return OneLogin_Saml2_Auth(saml_request, saml_config)
Exemple #29
0
    def testLogin(self):
        """
        Tests the login method of the OneLogin_Saml2_Auth class
        Case Login with no parameters. An AuthnRequest is built an redirect executed
        """
        settings_info = self.loadSettingsJSON()
        request_data = self.get_request()
        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info)

        target_url = auth.login()
        parsed_query = parse_qs(urlparse(target_url)[4])
        sso_url = settings_info['idp']['singleSignOnService']['url']
        self.assertIn(sso_url, target_url)
        self.assertIn('SAMLRequest', parsed_query)
        self.assertIn('RelayState', parsed_query)
        hostname = OneLogin_Saml2_Utils.get_self_host(request_data)
        self.assertIn(u'http://%s/index.html' % hostname, parsed_query['RelayState'])
Exemple #30
0
    def testLogoutWithRelayState(self):
        """
        Tests the logout method of the OneLogin_Saml2_Auth class
        Case Logout with relayState. A logout Request with a the RelayState in
        the assertion is built and redirect executed
        """
        settings_info = self.loadSettingsJSON()
        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        relay_state = 'http://sp.example.com'

        target_url = auth.logout(relay_state)
        parsed_query = parse_qs(urlparse(target_url)[4])
        slo_url = settings_info['idp']['singleLogoutService']['url']
        self.assertIn(slo_url, target_url)
        self.assertIn('SAMLRequest', parsed_query)
        self.assertIn('RelayState', parsed_query)
        self.assertIn(relay_state, parsed_query['RelayState'])