diff --git a/src/plone/restapi/setuphandlers.py b/src/plone/restapi/setuphandlers.py index 535653c02c..5bd8075eb3 100644 --- a/src/plone/restapi/setuphandlers.py +++ b/src/plone/restapi/setuphandlers.py @@ -80,6 +80,7 @@ def install_pas_plugin(context): default_challenge_plugin, HTTPBasicAuthHelper.HTTPBasicAuthHelper, ) and cookie_plugin_ids: + basic_plugin = default_challenge_plugin challenge_plugin_ids = [ challenge_plugin_id for challenge_plugin_id, _ in challenge_plugins ] @@ -93,6 +94,17 @@ def install_pas_plugin(context): plugins_ifaces.IChallengePlugin, [cookie_plugin_ids[0]], ) + reset_plugin_ids = [ + reset_plugin_id for reset_plugin_id, _ in + uf.plugins.listPlugins(plugins_ifaces.ICredentialsResetPlugin) + ] + if basic_plugin.id in reset_plugin_ids: + # Prevent the HTTP `Authorization: Basic ...` plugin from interfering + # with expiring the cookies from other plugins. + uf.plugins.deactivatePlugin( + plugins_ifaces.ICredentialsResetPlugin, + basic_plugin.id, + ) # Go up one more level if uf_parent is uf_parent.getPhysicalRoot(): diff --git a/src/plone/restapi/tests/test_functional_auth.py b/src/plone/restapi/tests/test_functional_auth.py index c62eb9e245..fb83c1846d 100644 --- a/src/plone/restapi/tests/test_functional_auth.py +++ b/src/plone/restapi/tests/test_functional_auth.py @@ -364,6 +364,40 @@ def test_api_logout_expires_both_cookies(self): "API token cookie remains after API logout POST response", ) + def test_root_zmi_logout_expires_api_token(self): + """ + Zope root ZMI logout succeeds and deletes all auth cookies. + """ + browser = zope.Browser(self.app) + + # Submit the login form in the browser + browser.open(self.app.absolute_url() + "/manage_main") + login_form = browser.getForm() + login_form.getControl(name="__ac_name").value = SITE_OWNER_NAME + login_form.getControl(name="__ac_password").value = TEST_USER_PASSWORD + login_form.controls[-1].click() + + # Click the ZMI logout link + browser.raiseHttpErrors = False + logout_link = browser.getLink(url="manage_zmi_logout") + logout_link.click() + browser.raiseHttpErrors = True + self.assertNotIn( + "__ac", + browser.cookies, + "Zope root auth cookie missing from Zope root basic login form response", + ) + self.assertNotIn( + "auth_token", + browser.cookies, + "API token cookie missing from Zope root basic login form response", + ) + + # Confirm the browser is, in fact, logged out + browser.open(self.app.absolute_url() + "/manage_main") + logout_login_form = browser.getForm() + logout_login_form.getControl(name="__ac_name") + def test_accessing_private_document_with_valid_token_succeeds(self): # login and generate a valid token response = requests.post(