WarningInterceptConfiguration
Current File(s): conf/intercept/warning-intercept-config.xml
Format: Native Spring, Velocity
Overview
The "warning" interceptor flow is a generalization of the older "expiring-password" flow that supports an arbitrary number of conditions and warning views at the same time in support of multiple use cases without requiring duplication of and creation of custom webflows by the deployer. It can support the original expiring password use case but is not limited to that. Nor in fact is the original flow limited to that use case, but this makes that generality clearer and corrects some confusing behavior in the original.
All interceptors are enabled or disabled on a per-relying-party basis using properties in the profile bean(s) you want to enable the flow for. See the ProfileInterceptConfiguration topic for an example.
Enabling Module
Configuring and using this feature requires that you first enable the "idp.intercept.Warning" module if it isn't already enabled. Systems upgraded from older releases generally come pre-enabled due to the prior state of the configuration tree.
(Windows)
C:\opt\shibboleth-idp> bin\module.bat -t idp.intercept.Warning || bin\module.bat -e idp.intercept.Warning
(Other)
$ bin/module.sh -t idp.intercept.Warning || bin/module.sh -e idp.intercept.Warning
General Configuration
The primary configuration involved with this flow is to define the condition(s) you want to evaluate, and which custom view template to display. Unlike the "expiring-password" flow, this implementation uses the more logical convention that the warning condition should evaluate to true to indicate that a warning should occur.
The bean named shibboleth.warning.ConditionMap in conf/intercept/warning-intercept-config.xml must be defined by you with the condition(s) you want to test and the additional information needed to control the warning process. Each map entry represents a unique warning, and the map is iterated over to test for and present all applicable views.
The keys in the Map are view template names resolved relative to views/intercept/ (e.g. the key "mywarning" would normally resolve to a template in idp.home/views/intercept/mywarning.vm
The Map values are beans of type Pair<Predicate<ProfileRequestContext>,Duration>> (the complex type is needed to associate both the necessary settings with the map key).
The first element of the pair is the bean to evaluate to test the warning condition. If it returns true, the warning is applied and if it returns false, the warning does not apply to the request.
The second element of the pair is a Duration value representing the interval between warnings. Setting this to a zero value will cause the warning to appear on every request, while any other value represents an interval during which the warning will not appear.
A cookie for each warning entry in the map is used to track the last warning time, so clearing cookies will reset this behavior. The prefix of the cookie name can be changed if desired, with the map key added to the prefix to construct the unique cookie name, allowing different intervals and tracking per warning type.
This cookie will be cleared any time the condition evaluates to false, as this is generally appropriate. For more advanced cases, V5.1 introduces settings allowing more control over this behavior:
The property idp.warning.unsetCookieWhenFalse may be set to false to globally disable this behavior, in which case the cookie is never cleared by this flow.
A bean named shibboleth.warning.CookieCondition may be defined in warning-intercept-config.xml to supply a Predicate<String> to indicate whether to clear the cookie. The input value is the key in the map of warning conditions being processed, allowing different warnings to rely on the cookie differently.
For the latter, if you wish to create a scripted condition to support this use case, the “typical” parent bean for that won’t work as it assumes a different type of input. The class net.shibboleth.shared.logic.ScriptedPredicate is a more generic version that allows any type of input, but otherwise follows the same sort of pattern as the numerous examples of the shibboleth.Conditions.Scripted bean shown throughout the documentation.
Views
The view templates can largely be modeled on existing views, particularly the expiring-password.vm file, which illustrates how to advance the flow forward. For reference the variables generally available to the views are described in VelocityVariables though they are not specific to Velocity-based views.
Replacement of Expiring Password Flow
This more general/flexible flow can replace usage of the original flow by reversing the sense of the condition applied in that particular flow's configuration, and utilizing "expiring-password" as a map key (or just renaming the view template). Eventually we may deprecate the older flow because it has no functional advantage over this one.
Storage-Backed Cookies 5.1
By default, this flow relies on a per-browser cookie to track when warnings are issued and allow them to be intermittent instead of occurring on every request, based on a set interval. An advanced option exists to backstop the cookie with a server-side storage service (e.g., a database, generally). Records in storage will be created when a cookie is set and cleared when the cookie is unset, allowing use of other devices to essentially “recreate” the cookie on the fly from storage. This allows the warning interval to be applied per-user rather than per-device, at the cost of the additional overhead.
This is a best-effort mechanism that is not always going to work or result in consistent behavior because persistent storage calls are prone to failure for a wide variety of reasons, but it may be good enough to improve the user experience so is provided as an option.
Enabling this feature merely requires setting the property idp.cookie.StorageService to the name of a StorageService bean in your property configuration. (Testing may be done using the in-memory shibboleth.StorageService bean but that obviously provides limited benefit in most cases. And you would certainly never want to rely on the client-based storage service option for this as that provides no benefit at all.)
Reference