LibreIdP: Plugin Architecture
Now that I’ve clearly defined the mission statement of the LibreIdP project, I’d like to take an initial stab at architecting one potential solution to fulfill the requirements of the “trivial use case” from my previous post.
Micro-features
We’re doing to do architecture by “micro-feature.” I’m not sure whether that’s a term used by anyone other than myself, so I’ll define it here:
micro-feature: A logical interaction with an application that may form only a part of a use case, and is externally visible. Typically, smaller and easier to implement than a User Story.
It might not be totally clear based on the definition I’ve provided, so let’s start with the first example.
We expect that the following requirement will be met in the final design:
Where LibreIdP has been configured with the NGINX_HTTP_AUTH FRONTEND, when an HTTP REQUEST is received, if a valid authorization header is not provided, LibreIdP shall indicate an HTTP 401 Unauthorized RESPONSE with a WWW-Authenticate header that points to a user authentication form.
This is a big requirement, but it should be easy to imagine some architecture that meets this requirement.
Keeping in mind our plugin architecture, where this is really a requirement on the plugin, and not on LibreIdP itself, we can begin assembling some interfaces.
There’s a few things to note here. First, since we’re implementing plugins as
dynamic libraries, we need a way to configure them at load time. Eventually,
this will be provided by a parameter in a configuration file. But for now, it’s
sufficient to say that we have a struct IdpConfig
, which contains a list of
plugins to load. Perhaps these are just the plugin names, and we can infer the
path to the dynamic library at runtime based on some compile-time
configuration.
When we load the config, we look for a symbol that is perhaps called
idp_plugin_v1
, which is of type IdpPlugin_v1
.