I would like to use JSecurity (eventually in Grails apps) in conjunction with a custom enterprise-wide SSO system that is already in place. So the authentication would take place outside of JSecurity. However I would still like to use JSecurity for two reasons: authorization handling, as well as for authentication when doing development testing (when I cannot access the enterprise SSO system).
The custom SSO system puts an encrypted string into a cookie. Jarfiles are provided for decrypting the cookie and extracting the username, authentication status, etc.
A colleague has been investigating JSecurity, and he suggests that all that may be required is to create a custom RememberMeManager to get the authentication information from the encrypted cookie. Looking at this, it appears I could subclass WebRememberMeManager, and create a custom implementation of getSerializedRememberedIdentity(). The implementation of rememberSerializedIdentity() would be null, since that is handled by the custom SSO system. Then I would install this new CustomWebRememberMeManager, making sure to redirect to the external SSO system when appropriate. (In grails, looks like this might be as simple as changing the login action of the AuthController to redirect to the external SSO system. Does this mean that I don't have to implement a custom Realm?)
Does this approach seem reasonable? Are there things I should watch out for? Does this message belong on the grails list? =;^)
Thanks,
Tom Smith.
Re: External SSO provider
Hi Tom,
This shouldn't be too difficult.
You would probably still want to use JSecurity for both Authentication and Authorization, its just you would have a custom Realm that delegated authentication attempts to the external SSO provider using the SSO provider's API instead of using the SSO provider API directly in your application code.
I feel this is a much better approach, using JSecurity as a 'wrapper' framework for many different authc/authz/session/crytpo mechanisms, much like say, SLF4J or commons-logging act as wrapper APIs to many different underlying logging implementations. This also enables your 'switching out the SSO provider during testing' approach - just use a different Realm - no need to recode login actions.
The JSecurity Realm concept is the core mechanism that allows a JSecurity user to interface with any back-end data source or 3rd party provider.
Concerning RememberMe: it sounds like your custom implementation would be perfectly fine to acquire an assumed identity. Just remember that in JSecurity, being remembered is not the same as being authenticated (described in detail in the RememberMeAuthenticationToken JavaDoc).
Typically this isn't a a problem for SSO enabled applications because they might not write code like this:
if ( subject.isAuthenticated() ) {//do something
}
but instead write code like this:
if ( subject.getPrincipal() != null ) {//do something
}
This is because the subject's principal will be non-null if they are remembered _or_ authenticated, which is often what an SSO application cares about.
I hope this helps. We should be releasing 0.9.0 RC1 in the next day or two, which should simplify your configuration efforts (and subclassing) significantly. Please look out for it.
Also, please feel free to continue to ask questions - I'm always happy to help out.
Cheers,
Les
Good guidance
Les,
Thanks very much for the reply. I understand your point about using JSecurity as a wrapper, so I will be going down the path of creating a custom Realm that farms out the authentication (when appropriate) to the external SSO system. You may see me back with questions once I get started.
Thanks,
Tom.
Re: Re: External SSO provider
I just thought of something else - if you implicitly trust your SSO provider, which I'm assuming you do, then in your custom RememberMeManager implementation, you could actually automatically perform an authentication attempt the very first time that identity is being accessed. It would be a lazy simulated authentication.
For example, in your
RememberMeManager.getRememberedPrincipals()implementation:getRememberedPrincipals() {Subject subject = SecurityUtils.getSubject();
if ( !subject.isAuthenticated() ) {
subject.login( new SSOAuthenticationToken( rememberedIdentity ) );
}
return subject.getPrincipals();
}
Then you could use the subject.isAuthenticated() call and taglib anywhere in your app.
I dunno if that would work for you, but I'm just throwing out ideas ;)
Regards,
Les
implement vs. inherit
For this case, it looks to me like it would be easiest to create my own class implementing RememberMeManager, rather than subclassing AbstractRememberMeManager. You've given me the outline of getRememberedPrincipals, and I may even be able to get away with null implementations of the onXXX callbacks! Does this seem realistic?
Thanks,
Tom.
Re: implement vs. inherit
Hi Tom,
There's certainly nothing wrong with just implementing the RememberMeManager interface and doing your own thing. The basic implementations are there as extension points to handle the majority of use cases, but if your requirements are fairly specialized, it might make more sense for you to implement the interface directly.
Cheers,
Les
The "lazy simulated
The "lazy simulated authentication" sounds great for my situation. I'll give it a try next week, thanks!