authlib icon indicating copy to clipboard operation
authlib copied to clipboard

Loggout support

Open dwt opened this issue 4 years ago • 2 comments

Is your feature request related to a problem? Please describe.

I'd like Authlib to support logging out of open id connect servers. AFAIK this is handled through an additional spec - and I'm not sure I understand fully which spec is required for that.

Describe the solution you'd like

Login in Flask land pretty much looks like this:

@app.route('/auth/login')
def login():
    store_came_from()
    redirect_url = flask.url_for('authorize', _external=True)
    return oauth.oidc.authorize_redirect(redirect_url)

I wrote my own logout method like this:

@app.route('/auth/logout')
def logout():
    try:
        # According to OIDC spec end_session_endpoint is optional, so we can't rely on it being present
        if not has_valid_oidc_user() or not does_support_deauthorize():
            return flask.redirect(flask.request.args['came_from'])
        
        store_came_from()
        
        redirect_uri = flask.url_for('deauthorize', _external=True)
        return deauthorize_redirect(redirect_uri)
    finally:
        # make sure we clean the session
        flask.session.pop('token', None)

It would be quite helpful if the library was able to create the deauthorize_redirect() the same way that it creates the authorize_redirect().

My version is quite simple, but took surprisingly long to get it right:

def deauthorize_redirect(redirect_url):
    metadata = oauth.oidc.load_server_metadata()
    end_session_endpoint = metadata.get('end_session_endpoint')
    
    token = token_from_session()
    end_session_url = add_params_to_uri(end_session_endpoint, (
        ('id_token_hint', token['id_token']),
        ('post_logout_redirect_uri', redirect_url),
    ))
    
    return flask.redirect(end_session_url)

Describe alternatives you've considered

I implemented something myself - but I think this would be a very nice addition to the library.

dwt avatar Mar 23 '21 13:03 dwt

end_session_endpoint is defined by OpenID Connect Session Management 1.0, but this spec is still in draft status. I'm not going to add it until it is published.

lepture avatar Apr 27 '21 04:04 lepture

This seems to be related to #292. end_session is mentioned in:

  • https://openid.net/specs/openid-connect-rpinitiated-1_0.html
  • https://openid.net/specs/openid-connect-session-1_0.html
  • https://openid.net/specs/openid-connect-frontchannel-1_0.html
  • https://openid.net/specs/openid-connect-backchannel-1_0.html

azmeuk avatar May 24 '21 17:05 azmeuk

closed in favor of https://github.com/lepture/authlib/issues/292

It will be implemented in v1.3

lepture avatar Nov 01 '22 12:11 lepture

Hi

I am trying to implement @dwt's logout session method. However it puzzles me how did he routed to the endpoint (deauthorize).

def deauthorize_redirect(redirect_url):
    metadata = grundfos.load_server_metadata()
    end_session_endpoint = metadata.get("end_session_endpoint")

    token = session.get("token")
    end_session_url = add_params_to_uri(
        end_session_endpoint,
        (
            ("id_token_hint", token["id_token"]),
            ("post_logout_redirect_uri", redirect_url),
        ),
    )

    return redirect(end_session_url)

So I cannot generate the redirect_uri , because the app doesn't have deauthorize endpoint.

@server.route("/logout")
def logout():
    # make sure we clean the session
    try:
        #Fails here, because there is no endpoint like deauthorize
        redirect_uri = url_for('deauthorize', _external=True)
        return deauthorize_redirect(redirect_uri)
    finally:
        # make sure we clean the session
        session.pop('token', None)

So question, how do you add or generate this redirect_uri ?

Error message: werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'deauthorize'. Did you mean 'authorize' instead? I understand there is no deauthorize.

Thanks

David

nagydavid avatar May 21 '23 14:05 nagydavid

@nagydavid Well, as you see in the example above, I implemented the endpoint /auth/logout myself - does that help you?

dwt avatar May 26 '23 06:05 dwt