Improving my PlonePAS plugin - questions about PlonePAS, pas.plugins.headers, and Shibboleth

Inspired by some discussion in Shibboleth and Volto? - #6 by yurj I started taking a deeper dive into my current Shibboleth PAS plugin (not (yet) public). The main thing I am considering for mine is if I should update it to create a session. Currently every request checks the Shibboleth headers and validates them with an Authentication plugin.

As I was considering this and looking into pas.plugins.headers, I wanted to step back and make sure that my assumptions about PlonePAS are correct. This code is stable, but ancient, a bit arcane, and I found the documentation limited. Do I have any misconceptions here that the community can disabuse me of?

  • The general workflow of plugins in a request is to loop through all of the extractCredentials and for each of those loop through all authenticateCredentials. Presumably this follows the order they are set in the ZMI. When the first authenticateCredentials is successful it stops and the user is authenticated.
  • updateCredentials is not called in the above workflow, I think. It needs to be explicitly called, such as in a login, login renew, or password update view, instead of something that happens on every request
  • getPropertiesForUser - I think this is additive to Plone's user defined properties? Meaning, you can't use this to update already defined user properties, like email address. If I wanted to update that property from the user to match what comes from a Shibb header I could maybe use an authenticate credentials plugin or maybe an update credentials plugin. Or do it during login, if you are creating a session.

With that context, these are my assumptions and questions about pas.plugins.headers @mauritsvanrees

  • If create session is True, a session token is created in authenticateCredentials. This creates a (new) session cookie on every request. Is the idea to send Shibb headers only on /@@headerlogin? So you call @@headerlogin, and authenticate only with the session cookie from this point until it expires/invalidates. Just a guess here, but is it something like - visit a restricted area, you are directed to @@headerlogin or directly to a Shibb url. This requires a Shibb session so you login with an IdP. This returns to @@headerlogin, where the authentication plugin creates your session and redirects to the original page.
  • The plugin defines a user id header, which must be a 1:1 match with Plone user id. This does not ensure that it is unique, as far as I can tell. If you have configured IdP1 and IdP2 and have a Plone user named "wohnlice" I could log in with either IdP

The plugin I am using was made in house and specific to our needs, but there are aspects of it that may be of interest to a larger community. I would like to split off a large part of this into an open source project and would be interested to know if anyone would find them useful. A lot of these are strict security measures needed for our authority to operate some government resources and may not be necessary for less critical projects. Regardless, I haven't seen anyone else handle these needs yet:

  • Plone accounts must be linked to an IdP account explicitly. We do not assume IdP id is a direct match to Plone user id, and for security reasons you may only link your account to one IdP
  • The password reset tool was repurposed to instead do this linking process. For example, to register a user they are given an email link with a unique key generated and consumed by that tool.
  • Plone/Zope has a distinction between user id and user login name. Many implementations treat these equally, we do not. The user id is what you are used to seeing in Plone, e.g. "wohnlich". The login name is the user's id from their IdP coupled with that IdP, e.g. "wohnlich@imsweb.com". This is to ensure the account is tied to only one IdP
  • Active status property is added - active/inactive/disabled. This can be manually set, but is also automatically set as a security measure by a cron job. If a user hasn't logged in after X days they are inactive, if they haven't logged in after Y days they are disabled. Inactive users can self re-activate by verifying their email address.
  • UX for discrepancies between Shibb state and linked Plone. A common case our users found was that they would log in with an IdP but it was not linked to a Plone user. For example, maybe they have a Login.gov account and successfully logged in, but they do not have access to the site's resources. Plone considers them anonymous, but that is potentially confusing. What we did is add some info to the request annotations during the extract/authenticate plugin steps that identifies them as authenticated but unauthorized. Viewlets (Classic UI) read this info and present a message to the user accordingly. It would be simple to add reducers/components in Volto to do this.
  • Mail templates - register custom templates with ZCML for registration/relink/success. This generates a vocabulary you can select from the in the control panel. These templates are then used for the registration/relink emails. Example: site allows NIH and Login.gov. We want the registration email to instruct them to use either of these (links included) to complete user registration, or if they don't yet have an account they should use Login.gov.