Over the past several months, I have written several blogs about my project, the ArkCase framework. In this post, I will cover how we have gotten ArkCase to work with Spring Security. It is important to note that each organization has their own user directory, their own authentication rules, their own way of doing things. Spring Security supports every conceivable scheme, so starting with Spring Security is a no-brainer. But how can my project support configuring Spring Security at runtime?
How Other Products Do It
Alfresco supports authentication configuration at initial time of deployment . The administrator configures properties files to support one or more authentication chains . Alfresco reads these properties files at startup time. When users login, Alfresco tries to authenticate against each link in the authentication chain. Alfresco ships with support for NTLM , passthru , LDAP  (both non-Active Directory and Active Directory), Kerberos , and external authentication. This approach is obviously very good seeing how widely-used Alfresco is, but leaves some of Spring Security’s reach and flexibility behind.
JIRA supports authentication configuration at runtime. After initial installation, JIRA has one admin user. That user logs in and uses the web user interface to configure one or more user directories . The directory support is more limited: JIRA internal directory , Active Directory or other LDAP servers , Atlassian Crowd or another JIRA server . As with Alfresco you can stack up as many directories as you need, even multiple Active Directory configurations. This approach must also be very good since JIRA may be more widely used than Alfresco. But it still leaves some of Spring Security behind.
ArkCase Authentication Goals
For ArkCase, I want to be able to support most any authentication scheme out of the box; again, that’s why we’re using Spring Security. But I don’t want to specify a new property file system, like Alfresco, or write a web user interface like JIRA. Such work is very exacting, requires a backbreaking regime of testing, and never quite gets you all the way to complete Spring Security coverage.
Not that Alfresco’s and JIRA’s approaches are wrong; I’ll be very happy when ArkCase achieves the tiniest fraction of their success. Still, I want to try something different.
ArkCase should be able to read Spring Security configurations at runtime, passing authentication requests to each such Spring Security configuration. Once such a configuration approves the authorization request, the user is logged in. If they all reject the request, the user sees the error message from the last configuration.
How It Works
My solution does have a few moving pieces.
- A folder watcher that raises events when Spring configuration files are added, updated, or removed in the system configuration folder
- A Spring context manager that adds, updates, or removes Spring child contexts based on the content of such Spring config files
- A custom AuthenticationManager that iterates over a set of AuthenticationProviders , as described above. It gets the authentication providers by asking the Spring context holder for all AuthenticationProvider instances.
Here’s a simple activity diagram showing how an authentication provider is added:
And here’s a simple activity diagram showing how an authentication provider is removed:
And finally, here’s a diagram showing the user authentication process:
This solution definitely meets my goals. It supports any Spring Security authentication provider, does not require new configuration file formats (it uses the well-known Spring configuration file), and requires no Web user interface. It does not even require the initial administrator user!
The solution does have some problems though. Only the Spring configuration files are loaded. This means any classes required by the Spring configuration must already be available. And this means we have to ship the web application with every Spring Security module! Since we can’t know beforehand which module any specific customer may need.
These problems actually point to their own solution. In the future I want to extend this mechanism to be a full-fledged plugin system. Many popular Web applications are based on plugins: Alfresco and JIRA (mentioned above), also Jenkins  and many others. These plugin systems allow users to add custom classes, behavior, and user interface elements at runtime. JIRA and Jenkins don’t even require restarts! So I want ArkCase to be the same. I will write more blogs documenting my progress.
- Alfresco Help: Setting up Alfresco Authentication and Security
- Alfresco: Authentication Configuration Examples
- Alfresco: Configuring alfrescoNtlm
- Alfresco: Configuring pass thru
- Alfresco: Configuring LDAP
- Alfresco: Configuring Kerberos
- JIRA: Configuring User Directories
- JIRA: Configuring the Internal Directory
- JIRA: Connecting to an LDAP Directory
- JIRA: Connecting to Atlassian Crowd
- Spring IO: Custom AuthenticationManager
- Spring IO: Custom AuthenticationProvider
- Jenkins: Open Source Integration Server