From 75dbcdfd580c119059cd4dd8a82e23e69dd52cbb Mon Sep 17 00:00:00 2001 From: Ross Patterson Date: Sun, 13 Feb 2022 11:44:36 -0800 Subject: [PATCH] feat(setup): Zope root cookie login form profile Move the change of the default Zope root configuration from HTTP Basic auth to the cookie login form [into a separate GenericSetup upgrade step to make the change optional](https://github.com/plone/plone.restapi/pull/1304#issuecomment-1004702508). This reverts commit 132c2c390801ff16393f214c1501252b240cb62a. --- src/Products/PlonePAS/profiles.zcml | 16 +++++++ .../profiles/root-cookie/metadata.xml | 4 ++ .../plone-pas-zope-root-cookie.txt | 2 + src/Products/PlonePAS/setuphandlers.py | 47 +++++++++++++++---- src/Products/PlonePAS/tests/test_setup.py | 24 +++++----- 5 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 src/Products/PlonePAS/profiles/root-cookie/metadata.xml create mode 100644 src/Products/PlonePAS/profiles/root-cookie/plone-pas-zope-root-cookie.txt diff --git a/src/Products/PlonePAS/profiles.zcml b/src/Products/PlonePAS/profiles.zcml index 2b93de24..74286bdd 100644 --- a/src/Products/PlonePAS/profiles.zcml +++ b/src/Products/PlonePAS/profiles.zcml @@ -21,4 +21,20 @@ + + + + + diff --git a/src/Products/PlonePAS/profiles/root-cookie/metadata.xml b/src/Products/PlonePAS/profiles/root-cookie/metadata.xml new file mode 100644 index 00000000..cf4492ac --- /dev/null +++ b/src/Products/PlonePAS/profiles/root-cookie/metadata.xml @@ -0,0 +1,4 @@ + + + 1 + diff --git a/src/Products/PlonePAS/profiles/root-cookie/plone-pas-zope-root-cookie.txt b/src/Products/PlonePAS/profiles/root-cookie/plone-pas-zope-root-cookie.txt new file mode 100644 index 00000000..a0844b6c --- /dev/null +++ b/src/Products/PlonePAS/profiles/root-cookie/plone-pas-zope-root-cookie.txt @@ -0,0 +1,2 @@ +Change the Zope root `/acl_users` to use a simple cookie login form instead of HTTP +`Basic ...` for authentication. diff --git a/src/Products/PlonePAS/setuphandlers.py b/src/Products/PlonePAS/setuphandlers.py index daabb2f7..e6f1fe3a 100644 --- a/src/Products/PlonePAS/setuphandlers.py +++ b/src/Products/PlonePAS/setuphandlers.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- +""" +Custom GenericSetup import steps for PAS in Plone. +""" + from Acquisition import aq_base from Acquisition import aq_parent from Products.CMFCore.utils import getToolByName @@ -324,14 +328,9 @@ def migrate_root_uf(self): pas = uf.manage_addProduct['PluggableAuthService'] plone_pas = uf.manage_addProduct['PlonePAS'] # Setup authentication plugins - setupAuthPlugins( - parent, - pas, - plone_pas, - deactivate_basic_reset=False, - # Switch from HTTP `Authorization: Basic ...` to cookie login form - deactivate_cookie_challenge=False, - ) + setupAuthPlugins(parent, pas, plone_pas, + deactivate_basic_reset=False, + deactivate_cookie_challenge=True) # Activate *all* interfaces for user manager. IUserAdder is not # activated for some reason by default. @@ -518,3 +517,35 @@ def setupPlonePAS(context): addRolesToPlugIn(site) setupGroups(site) setLoginFormInCookieAuth(site) + + +def set_up_zope_root_cookie_auth(context): + """ + Change the Zope root `/acl_users` to use a simple cookie login form. + """ + # Only run step if a flag file is present, IOW not for every profile + if context.readDataFile("plone-pas-zope-root-cookie.txt") is None: + return + portal = context.getSite() + root = portal.getPhysicalRoot() + root_acl_users = getToolByName(root, "acl_users") + + # Enable the cookie plugin for all interfaces + activatePluginInterfaces(root, "credentials_cookie_auth") + # Ensure that the cookie login form is used to challenge for authentication + credentials_cookie_auth = root_acl_users._getOb( # pylint: disable=protected-access + "credentials_cookie_auth", + ) + root_acl_users.plugins.movePluginsTop( + IChallengePlugin, + [credentials_cookie_auth.id], + ) + # Disable the HTTP `Basic ...` authentication plugin + root_acl_users.plugins.deactivatePlugin( + IChallengePlugin, + 'credentials_basic_auth' + ) + root_acl_users.plugins.deactivatePlugin( + ICredentialsResetPlugin, + 'credentials_basic_auth' + ) diff --git a/src/Products/PlonePAS/tests/test_setup.py b/src/Products/PlonePAS/tests/test_setup.py index dc2ef98f..ae851272 100644 --- a/src/Products/PlonePAS/tests/test_setup.py +++ b/src/Products/PlonePAS/tests/test_setup.py @@ -29,12 +29,13 @@ def setUp(self): """ self.app = self.layer["app"] self.root_acl_users = self.app.acl_users + self.portal = self.layer["portal"] - def test_zope_root_basic_challenge(self): + def test_zope_root_default_challenge(self): """ - The Zope root `/acl_users` basic challenge plugin works. + The Zope root `/acl_users` default challenge plugin works. """ - # Make the basic plugin the default auth challenge + # Check the Zope root PAS plugin configuration self.assertIn( "credentials_basic_auth", self.root_acl_users.objectIds(), @@ -46,11 +47,6 @@ def test_zope_root_basic_challenge(self): HTTPBasicAuthHelper.HTTPBasicAuthHelper, "Wrong Zope root `/acl_users` basic auth plugin type", ) - self.root_acl_users.plugins.movePluginsTop( - plugins_ifaces.IChallengePlugin, - [basic_plugin.id], - ) - transaction.commit() challenge_plugins = self.root_acl_users.plugins.listPlugins( plugins_ifaces.IChallengePlugin, ) @@ -68,14 +64,18 @@ def test_zope_root_basic_challenge(self): self.assertEqual( browser.headers["Status"].lower(), "401 unauthorized", - "Wrong Zope root `/acl_users` basic challenge response status", + "Wrong Zope root `/acl_users` default challenge response status", ) - def test_zope_root_default_login(self): + def test_zope_root_cookie_login(self): """ - The Zope root `/acl_users` default login works. + The Zope root `/acl_users` cookie login works. """ - # Check the Zope root PAS plugin configuration + # Install the GenericSetup profile that performs the actual switch + pa_testing.applyProfile(self.portal, 'Products.PlonePAS:root-cookie') + transaction.commit() + + # Make the cookie plugin the default auth challenge self.assertIn( "credentials_cookie_auth", self.root_acl_users.objectIds(),