External authentication with old-Zope

I've been attempting to develop a SAML solution for our old-Zope 2.10 off and on since September. I've been grateful for the help I've been given throughout this process.

There are complications preventing us from upgrading to Zope 2.12 or 2.13, and I've been unable to get dm.zope.saml2 installed. The advice given back in September was to use the Apache mod_auth_mellon module to perform the SAML SP duties, then write a PAS plugin. check, and check

It was an adventure even getting my plugin to show up in the Add-list, but it is there now, thankfully.

My issue is Mellon unpacks all the SAML Attributes from the SAML token into the environment, but Zope seems to clobber the environment before my plugin even runs.

If I do not start Zope and instead run a simple Apache website, I can run a simple WSGI application and grab the SAML attributes out of the environment like this:

from webob import dec, Response

@dec.wsgify
def application(req):
  user = {'uid': '', 'role': '', 'phone': '', 'lastName': '', 'firstName': ''}
  user['uid'] = req.environ['MELLON_urn:oid:0.9.2342.19200300.100.1.1']
  user['role'] = req.environ['MELLON_https://samltest.id/attributes/role']
  user['phone'] = req.environ['MELLON_urn:oid:2.5.4.20']
  user['lastName'] = req.environ['MELLON_urn:oid:2.5.4.4']
  user['firstName'] = req.environ['MELLON_urn:oid:2.5.4.42']
  #return Response(pprint.pformat(req.environ), content_type='application/json')
  return Response(pprint.pformat(user), content_type='application/json')

The Zope we run is Zope 2.10.6, but it appears it was originally installed using the Plone 3.1.1 universal installer. But, we do not run a Plone-site, we run Zope.

Is there a way to get the environment into PAS? I've tried having my plugin implement zope.publisher.interfaces.http.IHTTPApplicationRequest, but when my plugin runs, it simply ignores any code using that interface. I have 3 logging statements in my authenticateCredentials function, and only one of those statements logs anything.

The Zope documentation tells that non-CGI header names are renamed (e.g. they get a HTTP_ prefix). At least modern versions (much more modern than yours) can also drop headers.

First step is to check what headers arrive in request.environ in your case. I use a DTMLMethod for this with the source <dtml-var REQUEST>.
With such a method, you can determine whether the SAML headers have been renamed or dropped. If they have been renamed, you can adapt your plugin to the correct names.

1 Like

Note that HTTP in based on MIME. This implies that an HTTP header has the form name:value. Your example above indicates that your name contains a colon. To achieve this special syntax is required (to prevent the embedded colon to terminate name). Zope may not support this special syntax and misinterpret the headers containing a colon in their names.

Can you configure your "MELLON" component to use more typical header names (at least names without a colon).

No. Those are the SAML attribute names straight out of the token. The only thing Mellon does is prepend the "MELLON_" string. That prefix is configurable, but not the rest.

There is nothing SAML related in the "environ" section of what gets dumped by that DTML Method, other than the HTTP_REFERER, which it does list as the IDP.

The header processing is in ZServer.HTTPServer.zhttp_handler.get_environment. You could add logging there to find out whether the SAML headers reach this place. If you look at the header processing in this function, you will notice that it is not prepared to correctly process header names with embedded colons (the header name stops at the first colon). It also lacks support for quoted colons. This implies that you will need changes there to get your SAML headers through to your application.

If you do not see the SAML headers there, then either the frontend does not send them or they have already been filtered out (I doubt that the latter case occurs).

1 Like

This assumes that you use HTTP to connect your web server with Zope. Should you use a different interface, locate the header processing in its source code and intervene as necessary.

Is HTTPS considered different?
ZPublisher handles http and https in the same funcitons. ZServer has no mention of https.

Also, I've attempted to add logging to ZServer. Just like in my Plugin, the logging statements do not log anything.

The standard ZServer does not support "https" (there an add-on for that). Usually, there is a web server in front of Zope which handles "https" (and "http") and communicates with Zope via one of a variety of interfaces -- "http", "cgi", "fcgi", "wsgi", ...

I've tried searching for the HTTPS add-on for ZServer you mentioned. I'm not finding it. Could you please give some more info?
We're taking another look at updating to a newer Zope. We may have to go through the pain at this point.

Also, with a newer Zope, I understand WSGI is the new default server. Would there be any gotchas we should look for bringing our app built for old-Zope over?

https://m2crypto.readthedocs.io/en/latest/ZServerSSL-HOWTO.html

Usually, you put a web server before Zope. It can handle HTTPS and communicate via HTTP (or other protocols like WSGI, FCGI, ...) with Zope. Thus, you usually do not need direct HTTPS support by Zope.

Plone Foundation Code of Conduct