---
 aurweb/routers/sso.py | 18 ++++++++++++++++++
 web/html/logout.php   | 14 +++++++++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/aurweb/routers/sso.py b/aurweb/routers/sso.py
index e1ec7efe..a8d4b141 100644
--- a/aurweb/routers/sso.py
+++ b/aurweb/routers/sso.py
@@ -1,6 +1,8 @@
 import time
 import uuid
 
+from urllib.parse import urlencode
+
 import fastapi
 
 from authlib.integrations.starlette_client import OAuth
@@ -82,3 +84,19 @@ async def authenticate(request: Request, 
conn=Depends(aurweb.db.connect)):
     else:
         # We’ve got a severe integrity violation.
         raise Exception("Multiple accounts found for SSO account " + sub)
+
+
+@router.get("/sso/logout")
+async def logout():
+    """
+    Disconnect the user from the SSO provider, potentially affecting every
+    other Arch service. AUR logout is performed by `/logout`, before it
+    redirects to `/sso/logout`.
+
+    Based on the OpenID Connect Session Management specification:
+    https://openid.net/specs/openid-connect-session-1_0.html#RPLogout
+    """
+    metadata = await oauth.sso.load_server_metadata()
+    # TODO Supply id_token_hint to the end session endpoint.
+    query = urlencode({'post_logout_redirect_uri': 
aurweb.config.get('options', 'aur_location')})
+    return RedirectResponse(metadata["end_session_endpoint"] + '?' + query)
diff --git a/web/html/logout.php b/web/html/logout.php
index 14022001..9fd63943 100644
--- a/web/html/logout.php
+++ b/web/html/logout.php
@@ -5,16 +5,28 @@ set_include_path(get_include_path() . PATH_SEPARATOR . 
'../lib');
 include_once("aur.inc.php");         # access AUR common functions
 include_once("acctfuncs.inc.php");         # access AUR common functions
 
+$redirect_uri = '/';
+
 # if they've got a cookie, log them out - need to do this before
 # sending any HTML output.
 #
 if (isset($_COOKIE["AURSID"])) {
+       $uid = uid_from_sid($_COOKIE['AURSID']);
        delete_session_id($_COOKIE["AURSID"]);
        # setting expiration to 1 means '1 second after midnight January 1, 
1970'
        setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
        unset($_COOKIE['AURSID']);
        clear_expired_sessions();
+
+       # If the account is linked to an SSO account, disconnect the user from 
the SSO too.
+       if (isset($uid)) {
+               $dbh = DB::connect();
+               $sso_account_id = $dbh->query("SELECT SSOAccountID FROM Users 
WHERE ID = " . $dbh->quote($uid))
+                                     ->fetchColumn();
+               if ($sso_account_id)
+                       $redirect_uri = '/sso/logout';
+       }
 }
 
-header('Location: /');
+header("Location: $redirect_uri");
 
-- 
2.27.0

Reply via email to