SAML-Toolkits / python3-saml

MIT License
682 stars 304 forks source link

SLO/SLS Request does not log out properly #266

Closed VijoPlays closed 3 years ago

VijoPlays commented 3 years ago

Problem

I've integrated the flask-demo and, for the most part, things went fine, but I've hit a wall.

When sending the SLO Request I get logged out (on the IdP side) properly (a new SSO Request requires logging in again), however, it doesn't log me out on the client side.


Description

The HTTP Codes are all fine (either 200, or 302), but the problem seems to be, that the IdP can only send SLS Requests in the background (i.e. the client will be redirected to the IdPs "You've been logged out from this IdP.", instead of the /?sls-binding and a separate SLS Request is send in the background afterwards).

When grabbing the 'GET /?sls&SAMLResponse=...' from the Request sent in the background, and executing it on a new page, the client gets logged out locally, properly.

The IdP seems to be based on Shibboleth, but I don't know which version. It's just this one method that doesn't work.


Code

Index

@app.route('/', methods=["GET", "POST"])
@cross_origin(uniIdP_URL)
def indexSAML():

(...)
    elif 'sls' in request.args:
        request_id = None
        if 'LogoutRequestID' in session:
            request_id = session['LogoutRequestID']
        dscb = lambda: session.clear()
        url = auth.process_slo(request_id=request_id, delete_session_cb=dscb)
        errors = auth.get_errors()
        if len(errors) == 0:
            if url is not None:
                return redirect(url)
            else:
                success_slo = True
        elif auth.get_settings().is_debug_active():
            error_reason = auth.get_last_error_reason()

Settings

(...)
        "singleLogoutService": {
            "url": "https://localhost:8082/?sls",
            "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        }
(...)
VijoPlays commented 3 years ago

I dove into it again, and I pseudo-fixed it, it's not as pretty as waiting for the IdP to answer with a response, but this works:

def index:
(...)
    elif 'slo' in request.args:
        name_id = session_index = name_id_format = name_id_nq = name_id_spnq = None
        if 'samlNameId' in session:
            name_id = session['samlNameId']
        if 'samlSessionIndex' in session:
            session_index = session['samlSessionIndex']
        if 'samlNameIdFormat' in session:
            name_id_format = session['samlNameIdFormat']
        if 'samlNameIdNameQualifier' in session:
            name_id_nq = session['samlNameIdNameQualifier']
        if 'samlNameIdSPNameQualifier' in session:
            name_id_spnq = session['samlNameIdSPNameQualifier']
        response = make_response(redirect(auth.logout(name_id=name_id, session_index=session_index, nq=name_id_nq, name_id_format=name_id_format, spnq=name_id_spnq)))
        response.set_cookie('session', '', expires=0)
        return response
(...)

This just deletes the local cookie and then initiates the SLO process.