From ddaf5123c359428ed3a7fb94d498017a67b488e7 Mon Sep 17 00:00:00 2001 From: Arie Peterson <arie@greenhost.nl> Date: Thu, 19 Oct 2023 11:58:06 +0200 Subject: [PATCH] Retry failed logout attempts from the start in some cases --- backend/web/login/login.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/backend/web/login/login.py b/backend/web/login/login.py index 177bdd90..43c521c7 100644 --- a/backend/web/login/login.py +++ b/backend/web/login/login.py @@ -570,28 +570,41 @@ def logout(): Returns: Redirect to the url that is provided by the LogoutRequest object. """ + # Generally, if we encounter errors during these steps we redirect the user + # to the beginning of the logout procedure, which is + # `https://${hydra_domain}/oauth2/sessions/logout`. + new_logout_url = "https://{}/oauth2/sessions/logout".format(HYDRA_PUBLIC_URL) + + # We should have been redirected here by hydra which also sets the + # `logout_challenge` parameter. challenge = request.args.get("logout_challenge") current_app.logger.info("Logout request: challenge=%s", challenge) if not challenge: - abort(403) + current_app.logger.info("No challenge set.") + current_app.logger.info("Redirecting to hydra logout: %s", new_logout_url) + return redirect(new_logout_url) try: # hydra v2 # logout_request = oauth2_api.get_o_auth2_logout_request(challenge) logout_request = hydra_admin_api.get_logout_request(challenge) except hydra_exceptions.NotFoundException: current_app.logger.error("Logout request with challenge '%s' not found", challenge) - abort(404, "Hydra session invalid or not found") + return redirect(new_logout_url) except hydra_exceptions.ApiException: current_app.logger.error( "Conflict. Logout request with challenge '%s' has been used already.", challenge) - abort(404, "Logout request has been accepted already.") + current_app.logger.info("Redirecting to hydra logout: %s", new_logout_url) + return redirect(new_logout_url) current_app.logger.info("Logout request hydra, subject %s", logout_request.subject) - # Accept logout request. We ignore the redirect URL - # (`hydra_return.redirect_to`) because we also need to do the kratos logout - # browser flow and we can't do both. + # Accept logout request. The `redirect_to` that we get is what we have to + # redirect the browser to to finish the hydra logout (clear cookies, etc.) + # and after that get redirected to the configured post-logout URL. We store + # the `redirect_to` URL so we can pass it to kratos below (as `return_to`), + # so the browser will get redirected to `redirect_to` after the kratos + # logout is finished. try: hydra_return = hydra_admin_api.accept_logout_request(challenge) next_redirect = hydra_return.redirect_to @@ -603,7 +616,7 @@ def logout(): kratos_cookie = get_kratos_cookie() if not kratos_cookie: # No kratos cookie, already logged out from kratos. - current_app.logger.info("Expected kratos cookie but not found. Redirecting to hydra post-logout"); + current_app.logger.info("Expected kratos cookie but not found. Skipping kratos logout but continuing other logout steps."); # We skip the Kratos logout, but we still need to follow # `next_redirect` -- probably the Hydra logout URL -- and clear # dashboard storage. @@ -623,7 +636,8 @@ def logout(): current_app.logger.error("Exception when calling" " create_browser_logout_flow: %s\n", ex) - return redirect(DASHBOARD_URL) + current_app.logger.info("Redirecting to hydra logout: %s", new_logout_url) + return redirect(new_logout_url) if DEMO_INSTANCE: -- GitLab