Reputation: 609
My question mostly revolves around whether it's possible to have two login forms with separate authentication sources of truth presented to the same user in a Spring application.
I would like to have different security configuration classes (or the same class with static inner config classes) added to my Maven build depending on which profile is selected: UAT, or Production. Or control this with the deployment environment (see below about frames).
In either case the application should have its own authentication prompt for "privileged" access (like admin pages) and I would like to see the app's login page for this.
However, in the case of the UAT profile, I would like to see an additional login page before any user can view any page, as well as the login page for admin functionality if those protected pages are accessed.
The idea is to show the application in UAT exactly as it would operate in production, but without allowing any user to see any page without first authenticating with a separate login form.
I'm willing to look into any ideas, but my ideal case would be allowing this with distinct Spring Security configuration sets.
What I've tried/considered
Dynamic Filter I've had some luck with implementing this idea by registering a dynamic filter that caught any request and forwarded to a servlet whose sole purpose was to handle showing a different login page and handling the outer authentication (all packaged in a jar included at build time for UAT), but that wasn't a Spring app and I believe the dispatch servlet would negate that approach.
Frame (app-ception) I've considered the idea of displaying the app within the frame of an outer "UAT Viewer" app that would have its own security, theoretically segmenting the Spring Security concerns. But I don't know if that would create different cookies for the outer and inner app (I rarely consider frames for security reasons). Ideally I would like to deny all framing in the x-frame-options header to help prevent click-jacking, but if this approach is possible, I would be happy with only having to change the frame policy to same-origin.
I think I'll try the frame approach first and report back.
Thinking this through, the inner app that would be presented in the frame would still have to be accessible to the outside world so that the client could load it, so this approach defeats the purpose of isolating the inner application with minimal impact to its code.
Upvotes: 0
Views: 100
Reputation: 609
The solution is adding a dependency on a separate project (with a "UAT" profile in Maven) that provides a Filter and Servlet that can interrupt and handle authentication outside of the normal flow of spring security.
The problem with this approach is that spring security's filters will intercept the request first and attempt to redirect to the specified login page (or default) if the page requires authentication. The way to get around this is to add a path that disables spring security, so a request will bypass those filters and be handled by the custom added filter like so:
@Override
public void configure(WebSecurity web) throws Exception {
// Disabling security for the login-aspect addon. Will emit 404 in
// production operation where login-aspect.jar is no added.
web.ignoring().antMatchers("/uat-login");
}
In this way, I can have a filter that redirects any request to the application to an outer authentication servlet first that is mapped to '/uat-login' and shows an authentication prompt.
An added benefit (IMO) to this is that if the logout functionality of the application is triggered and the session cookie is deleted, then it effectively logs out of the outer security as well.
This may not be an optimal method, but it works Suggestions for improvement are certainly welcome. I think I'll post the code used to do this in a Github project at a later time.
Upvotes: 0