Skip to content

Commit beeb79d

Browse files
committed
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](plone/plone.restapi#1304 (comment)). This reverts commit 132c2c390801ff16393f214c1501252b240cb62a.
1 parent 955a276 commit beeb79d

File tree

6 files changed

+82
-20
lines changed

6 files changed

+82
-20
lines changed

news/zope-root-cookie.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Add separate `GenericSetup` profile to switch the Zope root `/acl_users` to use a simple
2+
cookie login form. Useful when Zope root login and logout need to synchronize
3+
authentication state between multiple plugins, which is not possible with HTTP `Basic
4+
...` authentication. [rpatterson] (#65)

src/Products/PlonePAS/profiles.zcml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,20 @@
2121
<depends name="rolemap" />
2222
</genericsetup:importStep>
2323

24+
<genericsetup:registerProfile
25+
name="root-cookie"
26+
title="Zope Root Cookie Login"
27+
description="Change the Zope root `/acl_users` to use a simple cookie login form
28+
instead of HTTP `Basic ...` for authentication."
29+
provides="Products.GenericSetup.interfaces.EXTENSION"
30+
/>
31+
<genericsetup:importStep
32+
name="zope-root-auth-cookie"
33+
title="Zope Root Cookie Login"
34+
description="Change the Zope root `/acl_users` to use a simple cookie login form
35+
instead of HTTP `Basic ...` for authentication."
36+
handler=".setuphandlers.set_up_zope_root_cookie_auth">
37+
<depends name="plonepas" />
38+
</genericsetup:importStep>
39+
2440
</configure>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0"?>
2+
<metadata>
3+
<version>1</version>
4+
</metadata>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Change the Zope root `/acl_users` to use a simple cookie login form instead of HTTP
2+
`Basic ...` for authentication.

src/Products/PlonePAS/setuphandlers.py

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# -*- coding: utf-8 -*-
2+
"""
3+
Custom GenericSetup import steps for PAS in Plone.
4+
"""
5+
26
from Acquisition import aq_base
37
from Acquisition import aq_parent
48
from Products.CMFCore.utils import getToolByName
@@ -324,14 +328,9 @@ def migrate_root_uf(self):
324328
pas = uf.manage_addProduct['PluggableAuthService']
325329
plone_pas = uf.manage_addProduct['PlonePAS']
326330
# Setup authentication plugins
327-
setupAuthPlugins(
328-
parent,
329-
pas,
330-
plone_pas,
331-
deactivate_basic_reset=False,
332-
# Switch from HTTP `Authorization: Basic ...` to cookie login form
333-
deactivate_cookie_challenge=False,
334-
)
331+
setupAuthPlugins(parent, pas, plone_pas,
332+
deactivate_basic_reset=False,
333+
deactivate_cookie_challenge=True)
335334

336335
# Activate *all* interfaces for user manager. IUserAdder is not
337336
# activated for some reason by default.
@@ -518,3 +517,40 @@ def setupPlonePAS(context):
518517
addRolesToPlugIn(site)
519518
setupGroups(site)
520519
setLoginFormInCookieAuth(site)
520+
521+
522+
def set_up_zope_root_cookie_auth(context):
523+
"""
524+
Change the Zope root `/acl_users` to use a simple cookie login form.
525+
"""
526+
# Only run step if a flag file is present, IOW not for every profile
527+
if context.readDataFile("plone-pas-zope-root-cookie.txt") is None:
528+
return
529+
portal = context.getSite()
530+
root = portal.getPhysicalRoot()
531+
root_acl_users = getToolByName(root, "acl_users")
532+
533+
# Enable the cookie plugin for all interfaces
534+
activatePluginInterfaces(root, "credentials_cookie_auth")
535+
# Ensure that the cookie login form is used to challenge for authentication
536+
credentials_cookie_auth = root_acl_users._getOb( # pylint: disable=protected-access
537+
"credentials_cookie_auth",
538+
)
539+
root_acl_users.plugins.movePluginsTop(
540+
IChallengePlugin,
541+
[credentials_cookie_auth.id],
542+
)
543+
# Disable the HTTP `Basic ...` authentication plugin
544+
root_acl_users.plugins.deactivatePlugin(
545+
IChallengePlugin,
546+
'credentials_basic_auth'
547+
)
548+
# Apparently, the `HTTPBasicAuthHelper` plugin's `ICredentialsResetPlugin`
549+
# implementation interferes with deleting/expiring cookies, specifically the `__ac`
550+
# cookie in this case. I first tried moving that plugin to the top and bottom for
551+
# that interface, but the cookies still remained after logout. Only deactivating
552+
# it worked.
553+
root_acl_users.plugins.deactivatePlugin(
554+
ICredentialsResetPlugin,
555+
'credentials_basic_auth'
556+
)

src/Products/PlonePAS/tests/test_setup.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ def setUp(self):
2929
"""
3030
self.app = self.layer["app"]
3131
self.root_acl_users = self.app.acl_users
32+
self.portal = self.layer["portal"]
3233

33-
def test_zope_root_basic_challenge(self):
34+
def test_zope_root_default_challenge(self):
3435
"""
35-
The Zope root `/acl_users` basic challenge plugin works.
36+
The Zope root `/acl_users` default challenge plugin works.
3637
"""
37-
# Make the basic plugin the default auth challenge
38+
# Check the Zope root PAS plugin configuration
3839
self.assertIn(
3940
"credentials_basic_auth",
4041
self.root_acl_users.objectIds(),
@@ -46,11 +47,6 @@ def test_zope_root_basic_challenge(self):
4647
HTTPBasicAuthHelper.HTTPBasicAuthHelper,
4748
"Wrong Zope root `/acl_users` basic auth plugin type",
4849
)
49-
self.root_acl_users.plugins.movePluginsTop(
50-
plugins_ifaces.IChallengePlugin,
51-
[basic_plugin.id],
52-
)
53-
transaction.commit()
5450
challenge_plugins = self.root_acl_users.plugins.listPlugins(
5551
plugins_ifaces.IChallengePlugin,
5652
)
@@ -68,14 +64,18 @@ def test_zope_root_basic_challenge(self):
6864
self.assertEqual(
6965
browser.headers["Status"].lower(),
7066
"401 unauthorized",
71-
"Wrong Zope root `/acl_users` basic challenge response status",
67+
"Wrong Zope root `/acl_users` default challenge response status",
7268
)
7369

74-
def test_zope_root_default_login(self):
70+
def test_zope_root_cookie_login(self):
7571
"""
76-
The Zope root `/acl_users` default login works.
72+
The Zope root `/acl_users` cookie login works.
7773
"""
78-
# Check the Zope root PAS plugin configuration
74+
# Install the GenericSetup profile that performs the actual switch
75+
pa_testing.applyProfile(self.portal, 'Products.PlonePAS:root-cookie')
76+
transaction.commit()
77+
78+
# Make the cookie plugin the default auth challenge
7979
self.assertIn(
8080
"credentials_cookie_auth",
8181
self.root_acl_users.objectIds(),

0 commit comments

Comments
 (0)