Split logout flow in two steps (kratos/hydra)

This commit is contained in:
Mart van Santen 2022-09-21 23:51:28 +08:00 committed by Maarten de Waard
parent 0f36e955a8
commit 84ca20ba81
2 changed files with 41 additions and 13 deletions

View file

@ -29,4 +29,4 @@ if [[ -z "$HYDRA_CLIENT_SECRET" ]]; then
exit 1 exit 1
fi fi
KUBECTL_UID=${UID:-1001} KUBECTL_GID=${GID:-0} docker compose up KUBECTL_UID=${UID:-1001} KUBECTL_GID=${GID:-0} docker-compose up

View file

@ -385,21 +385,20 @@ def get_kratos_cookie():
return cookie return cookie
@web.route("/logout", methods=["GET"])
def logout(): @web.route("/prelogout", methods=["GET"])
"""Handles the Hydra OpenID Connect Logout flow as well as the Kratos def prelogout():
logout flow """Handles the Hydra OpenID Connect Logout flow
Steps: Steps:
1. Hydra's /oauth2/sessions/logout endpoint is called by an application 1. Hydra's /oauth2/sessions/logout endpoint is called by an application
2. Hydra calls this endpoint with a `logout_challenge` get parameter 2. Hydra calls this endpoint with a `logout_challenge` get parameter
3. We retrieve the logout request using the challenge 3. We retrieve the logout request using the challenge
4. We retrieve the Kratos cookie from the browser 4. We accept the Hydra logout request
5. We generate a Kratos logout URL 5. We redirect to Hydro to clean-up cookies.
6. We accept the Hydra logout request 6. Hyrda calls back to us with a post logout handle (/logout)
7. We redirect to the Kratos logout URL
Args: Args:
logout_challenge (string): Reference to a Hydra logout challenge object logout_challenge (string): Reference to a Hydra logout challenge object
@ -421,9 +420,39 @@ def logout():
challenge) challenge)
abort(503) abort(503)
current_app.logger.info("Logout request hydra, subject %s", logout_request.subject)
# Accept logout request and direct to hydra to remove cookies
try:
hydra_return = logout_request.accept(subject=logout_request.subject)
if hydra_return:
return redirect(hydra_return)
except Exception as ex:
current_app.logger.info("Error logging out hydra: %s", str(ex))
current_app.logger.info("Hydra logout not completed. Redirecting to kratos logout, maybe user removed cookies manually")
return redirect("logout")
@web.route("/logout", methods=["GET"])
def logout():
"""Handles the Kratos Logout flow
Steps:
1. We got here from hyrda
2. We retrieve the Kratos cookie from the browser
3. We generate a Kratos logout URL
4. We redirect to the Kratos logout URIL
"""
kratos_cookie = get_kratos_cookie() kratos_cookie = get_kratos_cookie()
if not kratos_cookie: if not kratos_cookie:
abort(404, "Kratos session invalid or not found") # No kratos cookie, already logged out
current_app.logger.info("Expected kratos cookie but not found. Redirecting to login");
return redirect("login")
try: try:
# Create a Logout URL for Browsers # Create a Logout URL for Browsers
kratos_api_response = \ kratos_api_response = \
@ -434,6 +463,5 @@ def logout():
current_app.logger.error("Exception when calling" current_app.logger.error("Exception when calling"
" V0alpha2Api->create_self_service_logout_flow_url_for_browsers: %s\n", " V0alpha2Api->create_self_service_logout_flow_url_for_browsers: %s\n",
ex) ex)
hydra_return = logout_request.accept(subject=logout_request.subject)
current_app.logger.info("Hydra info: %s", hydra_return)
return redirect(kratos_api_response.logout_url) return redirect(kratos_api_response.logout_url)