WebServerAuth

by WebLion Group last modified Mar 09, 2011 06:39 PM

WebServerAuth allows Plone to delegate authentication concerns to a web server like Apache or IIS. Using WebServerAuth, Plone can be configured so any user known to your LDAP, Kerberos, Shibboleth, or Pubcookie system—or any other system for which your web server has an authentication module—can transparently log in using enterprise-wide credentials. WebServerAuth replaces two earlier products, apachepas and AutoMemberMakerPasPlugin.

Project Description

Description

Authentication modules for web servers, like Apache or IIS, are more plentiful than those for Zope and Plone. WebServerAuth lets you take advantage of these in your site: just configure your web server to authenticate the user and store his or her login name in a request header, and WebServerAuth will convince Plone that that user is logged in. WebServerAuth has been used with LDAP, Active Directory, Kerberos, Shibboleth, Pubcookie, and CoSign and should work with anything else that can put a username into a header.

Requirements

  • Plone 3.0 or maybe even 3.1.3 or higher. (If it works with 3.0, please let me know.)
  • Also experimentally works on Zope without Plone, as long as you have PluggableAuthService. I've tested with Zenoss 2.3.3, which means Zope 2.8.8 and PluggableAuthService 1.4.

Upgrading

From an older version of WebServerAuth

  1. Shut down Zope.
  2. Install the new WebServerAuth as described in the Installation section below (either by copying it to your Products folder or by running buildout).
  3. Start up Zope.
  4. Go to your-plone-site → site setup → Add-on Products, and reinstall WebServerAuth. (Your settings will be preserved.)

From apachepas and/or AutoMemberMakerPasPlugin

  1. Follow the installation instructions under Installation, then return here. (Installing WebServerAuth before removing the old products will let you do the whole installation as a web-server-authenticated user.)
  2. Note your apachepas settings: in the ZMI, your-plone-site → acl_users → apachepas.
  3. Go to your-plone-site → site setup → Add-on Products, and uninstall both apachepas and AutoMemberMakerPasPlugin. If you like, remove them from your Products folder as well.
  4. Visit the WebServerAuth configuration page (in the ZMI, your-plone-site → acl_users → web_server_auth), and restore the settings you used with apachepas.
  5. If you were using AutoMemberMakerPasPlugin, select Any user the web server authenticates. (This is almost equivalent; see below.) If not, select Only users with a pre-existing Plone account.
  6. Click "Save Changes".

A subtle but important change from AutoMemberMakerPasPlugin

WebServerAuth does not grant users the Member role, only the Authenticated role (now that Plone supports that sort of thing without behaving erratically). This gives you the power to treat honest-to-goodness, explicitly endowed Members of your site differently than any idiot who authenticates to your web server. However, if you are upgrading from AutoMemberMakerPasPlugin, be sure to reexamine your site's permissions and workflows. If you want the same behavior as before, give Authenticated users all the privileges that Members previously had. If not, take this opportunity to differentiate the two roles.

Installation

  1. Secure Zope against HTTP requests from things other than Apache, because the following configuration will make it accept whatever login name comes in. Also secure any intermediaries between Apache and Zope (Pound, Varnish, Squid, etc.) from direct access, as they could also be used to inject a login name.
  2. Move the WebServerAuth folder into the Products folder of your Zope instance. Alternatively, add Products.WebServerAuth to your buildout.cfg like this and re-run buildout:
            [instance]
            eggs =
                ...(other eggs)...
                Products.WebServerAuth
  3. Go to your-plone-site → site setup → Add-on Products, and install WebServerAuth.
  4. Have your web server always prompt for authentication on the HTTPS side. Then, have it pass the login name of the logged in user in a header (for which you'll need the mod_headers module). For example, if you're using Apache, you might use something like this:
            <VirtualHost *:443>
                ServerName www.example.com
    
                # Prompt for authentication:
                <Location />
                    SSLRequireSSL
                    AuthType Basic
                    AuthName "My Funky Web Site"
                    AuthUserFile /etc/such-and-such
                    # etc.
                    Require valid-user
    
                    # Put the login name (stored below) into the HTTP_X_REMOTE_USER
                    # request header. This has to be in the <Location> block for
                    # some Apache auth modules, such as PubCookie, which don't set
                    # REMOTE_USER until very late.
                    RequestHeader set X_REMOTE_USER %{remoteUser}e
                </Location>
    
                # Some Linux distributions (e.g., Debian Etch and Red Hat Enterprise
                # Linux AS Release 4) have default settings which prevent the header
                # rewrites below from working. Fix that:
                <Proxy *>
                    Order deny,allow
                    Allow from all
                </Proxy>
    
                RewriteEngine On
    
                # Do the typical VirtualHostMonster rewrite, adding an E= option
                # that puts the Apache-provided login name into the remoteUser
                # variable.
                RewriteRule ^/(.*)$ http://127.0.0.1:8080/VirtualHostBase/https/%{SERVER_NAME}:443/VirtualHostRoot/$1 [L,P,E=remoteUser:%{LA-U:REMOTE_USER}]
            </VirtualHost>
  5. If you have a port-80 virtual host, be sure to clear out the HTTP_X_REMOTE_USER header so end users can't pass arbitrary login names directly to the web server and masquerade as any user they like:
            <VirtualHost *:80>
                ...
                RequestHeader unset X_REMOTE_USER
                ...
            </VirtualHost>
  6. Point Plone's Log Out link (in the ZMI: your-plone-site → portal_actions → user → logout) to something sensible. For example, if you're using a single-sign-on system that provides its own logout page, point to that. If you can't think of anything better, make a page that says "Sorry, Bub. You'll have to quit your web browser to log out", and point it to that. string:${portal_url}/logged_out may serve.
  7. Point the Change Password link (in the ZMI: your-plone-site → portal_controlpanel) to something sensible, or hide it altogether.
  8. Hide the Login portlet; it isn't meant to work with WebServerAuth. Your visitors will try to use it, and they'll get confused when it doesn't work. A future version of WebServerAuth will do this automatically.

Troubleshooting

In Plone's navigation bar, "(null)" shows up instead of the login name.

For some reason, the web server is not passing the HTTP_X_REMOTE_USER header to Zope. If you are using Apache, make sure you included the <Proxy *> block above.

I can't access any of the acl_users screens, add users, or do anything useful in the Plone site, but I can get into the root-level acl_users just fine.

If you have an existing user with the same ID as your user inside the Plone site, this will override your permission/role settings, so you can't access these things on an admin level anymore. Solution: Create a new user with a non-conflicting ID in the root folder, give it the Manager role, and log in with this user instead. Now the acl_users should behave normally again, and you should be able to change the settings.

Things act erratic when I use WebServerAuth to log in as a user that lives in the root-level acl_users folder.

This isn't supported yet. (See ticket 124 for details.) You'll have to remember separate passwords for root-level users for now.

Use

Once your web server is happily passing an authenticated login name to Plone via a request header, WebServerAuth kicks in and makes Plone consider that user logged in. To grant privileges to such a web-server-authenticated user...

  1. In Plone, create a user with the same login name. (The old AutoMemberMaker product would automatically create Plone users. This led to a profusion of uninteresting users in large organizations.)
  2. Assign privileges to that user as you normally would.

Configuration

WebServerAuth ships with sensible defaults, so you probably won't need to configure it at all. But if you do, first navigate to your WebServerAuth instance in the ZMI; it will be at your-plone-site → acl_users → web_server_auth. The configuration options are as follows:

Authenticate...

Any user the web server authenticates

To recognize everybody your web server recognizes, leave this option selected. The downside of this is that, if you have user folders enabled, anybody your web server knows will be able to make one. However, this option is the recommended one, because the UI is the most consistent (read on).

Only users with a pre-existing Plone account

If you want to authenticate only some of the users your web server recognizes, select this option, and use the Users and Groups page in Site Setup to create the users you want to have recognized. Users you don't create will still be able to get past your web server's login prompt but will not be recognized by Plone. This option is discouraged, because the UI is terrible: people will log in and apparently succeed, only to be greeted with a Plone page that still has a "Log In" link. However, it's the only way to have user folders and yet not give them out to every Tom, Dick, and Harry your web server recognizes. If somebody cares to donate themes that fix the UI, I'll be happy to include them.

To prompt the user for credentials, redirect...

To the HTTPS version of wherever he was going

When an anonymous user tries to access http://example.com/something-requiring-authentication, redirect him to https://example.com/something-requiring-authentication (note the "https").

To a custom URL

If the above doesn't suit you, you can customize the redirection behavior. In the Matching pattern box, enter a regular expression which matches every URL on your site and captures (using parentheses) the parts you'll need when constructing the URL to redirect to. In the Replacement pattern box, enter the URL to redirect to. Make sure it's an HTTPS URL, and use backreferences (like \1, \2, and so on) to substitute in the parts you captured above.

Strip domains from login names

Email-like domains

If your web server returns a login name that looks like fred@example.com, WebServerAuth will, by default, strip off everything from the @ onward. If you don't want it to do this (for example, if you are using a cross-domain authorization system like Shibboleth where this could cause name collisions), turn off this option.

Note that Plone will not let you create a user with an @ or a period in its login name. In order to assign privileges to a user with a domain in its name...

  1. In Plone, create a user with a temporary name.
  2. In source_users (in the ZMI: your-plone-site → acl_users → source_users), change the Login Name of the user to the full, domain-having name.

Windows domains

If your web server includes a Windows/Active Directory domain in the login name, turn this on to strip it off. For example, if the server sets HTTP_X_REMOTE_USER to "EXAMPLE\fred", turning this option on will shorten it to "fred". This can be useful if you are using Active Directory and sAMAccountName as the user id name, for example.

Login name is in the such-and-such header

If, for some reason, you cannot use the default HTTP_X_REMOTE_USER header (for instance, if you are using IISCosign, which has "HTTP_REMOTE_USER" hard-coded in), change the header WebServerAuth looks in here.

Only when the such-and-such cookie is present

In some situations, it is useful to be able to control whether the user is logged in or not based on a cookie, even if the actual authentication takes place outside Zope. For example, IIS can be configured to use integrated Windows authentication, in which case NTLM or Kerberos authentication will be used to set the X-Remote-User header. However, you may not want your users to appear logged in to Zope at all times, for example because you can cache content much more efficiently if everyone is anonymous.

The solution is to use a custom view or something outside Zope to set a cookie to indicate that the user should be logged in, and then enable this option. If the cookie is absent, the user will not be authenticated.

Ancestry

WebServerAuth obsoletes and improves upon apachepas and AutoMemberMakerPasPlugin, which come significantly and entirely, respectively, from the same author.

Improvements over apachepas and AutoMemberMakerPasPlugin

  • When an anonymous user tries to access something unpermitted, we redirect him to the HTTPS side, which triggers a proper login prompt. There are no more nonworking login forms popping up as in the old products.
  • No longer does every user who has ever logged in clutter up your Users and Groups control panel.
  • Grants all logged-in users the Authenticated role rather than the Member role, allowing site admins to treat the two differently. (Plone now supports this properly.) This means someone who authenticates to your web server doesn't necessarily get any privileges in your Plone site, making it safe to authenticate everyone; previously, when everyone got the Member role, certain default Plone workflows would grant them some capabilities.
  • Twiddles Plone's login link as necessary, reducing the need for manual configuration
  • Jettisons a lot of legacy code and requirements
  • Increases test coverage and does away with doctests
  • Is one product instead of two
  • Takes over the login_form so people can't log in wrong even if they try

Testing

To run the WebServerAuth tests, use the standard Zope testrunner:

        bin/instance test -pvvm Products.WebServerAuth

Future Plans

  • Execute political machinations necessary to let PAS find users who aren't enumerable so we can junk the hackish user enumerator.
  • Scheme and connive until Plone fires the IUserCreatedEvent properly, not just if the login form is used. Then we can get rid of the make-users-inside-an-auth-handler madness.
  • In stock Plone, users show up in the Users tab search (I'm not talking about the Users and Groups control panel, mind you) immediately after they're created. With WebServerAuth, they never show up. Does anybody care? Please file a ticket if you do. Otherwise, I might not bother.

Author

Erik Rose of the WebLion group at Penn State University

Thanks To...

  • Rocky Burt, who wrote the pre-1.1 versions of apachepas, which, along with my AutoMemberMakerPasPlugin, led to WebServerAuth.
  • Mark James for the ZMI icon, available from http://www.famfamfam.com/lab/icons/silk/.
  • Martin Aspeli for his work on versions 1.4 and 1.5.

Support

Contact the WebLion team at support@weblion.psu.edu or join our IRC channel, #weblion on irc.freenode.net. The WebLion wiki is full of good stuff.

Version History

1.6
  • Added option to check for the presence of a header before challenging, which makes ssh tunneling to Zope less impossible.
  • Factored the configuration and upgrade stuff, which was getting pretty long, out of plugin.py.
  • Added shared secret support.  A header (HTTP_WSA_SECRET by default) can be checked for an optional shared secret value.  When enabled and specfied, this value must match the header value for credential extraction to take place.
  • Reworked the ZMI options page to be more consistent.
1.5
  • Added option to check for the presence of a cookie before authenticating, which makes some Windows domain-based authentication scenarios easier.
  • Fixed a bug where configuration was accidentally shared instance-wide. Having different configs in different Plone sites works now.
  • Refactored tests, which had been working around this bug.
  • Fixed a bug where we were removing the wrong skin layer on uninstall.
  • Improved labeling on configuration page.
1.4
  • Added Windows domain stripping, thanks to Martin Aspeli.
1.3.1
  • Corrected egg installation instructions in readme.
1.3
  • Repackaged as an egg so buildout users can install it more easily.
1.2
  • Added redirection of login_form so it logs you in using WebServerAuth. Apparently, Plone's default commenting setup comes with a "Log in to add comments" button hard-coded to point to login_form. Blech!
  • A call to the WebServerAuth PAS plugin is used to compute the login link. Previously, it was hard-coded to use the portal-level acl_users folder. Now it uses the nearest one, in case somebody is crazy enough to define another.
1.1.2
  • Corrected a bug that kept users from being recognized when they had a domain in their login name and domain stripping was on.
  • Made the example regex a little tighter; I'd forgot to backslash the period.
  • Added experimental support for running on Zope without Plone. Works with Zenoss 2.3.3, anyway.
1.1.1
1.1
  • Provided for customization of where the challenge handler and login link send users.
  • Added even more instructions on setting up a secure Zope instance to the readme.
1.0
  • Polished the readme a bit. No code changes since 1.0b1.
1.0b1
  • First beta. No known bugs.

Self-Certification

[ ] Internationalized

[X] Unit tests

[X] End-user documentation

[X] Internal documentation (documentation, interfaces, etc.)

[X] Existed and maintained for at least 6 months

[X] Installs and uninstalls cleanly

[X] Code structure follows best practice

Current Release
Products.WebServerAuth webserverauth-1.7

Released Nov 13, 2012

Download file Get WebServerAuth for all platforms
Products.WebServerAuth-1.7.tar.gz
Download file Get WebServerAuth for all platforms
Products.WebServerAuth-1.7.zip
If you are using Plone 3.2 or higher, you probably want to install this product with buildout. See our tutorial on installing add-on products with buildout for more information.

All Releases

Version Released Description Compatibility Licenses Status
webserverauth-1.7 Nov 13, 2012 More about this release… GPL final
1.6 Mar 09, 2011 Shared secret and improved Plone 4 support. More about this release…
Plone 4
Plone 3
GPL final
1.5 Sep 18, 2009 Added an option to check for the presence of a cookie before authenticating, which makes some Windows domain-based authentication scenarios easier. Fixed various bugs. More about this release…
Plone 3
GPL final
1.4 Aug 17, 2009 Added an option for stripping Windows domains from login names. More about this release…
Plone 3
GPL final
1.3.1 Apr 24, 2009 Now there's an egg version, for people who roll like that. All that's added in the non-egg version are some egg-installation instructions in the readme. More about this release…
Plone 3
GPL final
1.2 Apr 16, 2009 Added redirection of login_form so it logs you in using WebServerAuth. This works around a Plone bug : the default commenting setup comes with a "Log in to add comments" button hard-coded to point to login_form . More about this release…
Plone 3
GPL final
1.1.2 Mar 13, 2009 Corrected a bug that kept users from being recognized when they had a domain in their login name and domain stripping was on. Added experimental support for use in plain Zope, without Plone. More about this release…
Plone 3
GPL final
1.1.1 Jan 12, 2009 Fixes spurious “Your custom WebServerAuth Matching Pattern did not match” error in the logs. More about this release…
Plone 3
GPL final
1.1 Dec 02, 2008 Provides for customization of where the challenge handler and login link send users. This lets you run more than one Plone site under a single domain, without buying lots of separate SSL certs. More about this release…
Plone 3
GPL final
1.0 Sep 16, 2008 A shiny, stable release More about this release…
Plone 3
GPL final