Why SSO?
Using single sign on (SSO) is probably something that more and more systems aim towards. A large benefit is improved user experience, perhaps not so much for publically available sites. These sites generally attach to Facebook, Twitter or Google and await the crowds going 'aaaaw' in appreciation of the the techniques used.
No, instead, imagine a portal used internally by an organization. Most probably the users also login to other web applications. Many.
Where I work a typical administrator log into tens of internal web applications each day. They add up quickly: webmail, liferay portal, HR-system to note your working hours etc, etc.
This is where SSO really shines.
But lets take a look at the Liferay portal. There are many ways of solving single sign on (like CAS and other plugins in Liferay or by using Shibboleth with the help of proxies filtering Tomcat), the one thing they have in common is: No password is ever stored locally in Liferay.
Well, that's not really true, there has to be a password. But it's not a password used by the user, most probably it is an auto generated field. The local password isn't really important in the case of authenticating a user logging in to the portal, as long as we trust someone else telling us that the user is authenticated. In CAS this is done by validating a ticket, in shibboleth by looking at extra headers in the request.
But there are some cases where the password plays an important role.
One is when the SSO framework is offline or simply doesn't work. Make sure you have an admin account that DOES have a local password otherwise it might be difficult to administer your portal in these cases! :)
Another is when using remote services generated by service builder, using webdav to access documents stored in your sites or similarly, when using Liferay Sync to replicate your documents to many devices! In these cases a local password is needed.
So, what are the options available to you as a developer in these cases?
If there was a way to insert your own authentication then perhaps you could verify the user yourself perhaps by binding towards an ldap or other.
I set out with my debugger trying to find a good extension point for the Liferay Sync method calls. Liferay sync uses the json-webservices for its interaction with the portal and currently uses preemptive basic authentication, which means that the username/password is sent in the request (hopefully over a secure transport layer).
After a lot of trial-and-error hacking with autologins, authenticators and extensions to the servlet filters I found a very easy path to success.
Enter UserLocalService.
Since Liferay Sync uses json webservices and basic authentication we will eventually end up in the UserLocalService. There are methods like authenticateByEmailAddress, authenticateByScreenName and authenticateByUserId that are being used (depending on portal-properties setting) to validate the password of a user.
By creating a simple hook-plugin and overriding these methods you're able to provide your own authentication! Perfect, just what we need! By overriding these methods you're also effectively changing the standard (http) login authentication but since Shibboleth intercepts those redirects the users won't be able to trigger your authentication code by logging into the portals web UI.
But what to authenticate against?
The SSO-password is of course a much valued resource. If decrypted a hacker would be able to access a large amount of systems. Storing this password on any device is probably not a good idea in the case of the device getting stolen, hacked or similar.
My idea was instead to generate tokens to be used per device and also individually revokeable. That way, if you loose your iPhone you can revoke the access for Liferay Sync for that phone only and not have to reset your SSO-password in all systems.
I solved this by creating a small portlet displaying all the currently generated tokens (really, just the description. The token itself is only shown to the user once, at creation, then encrypted) with the option to revoke. Then also a possibility to generate a new token with a given description. The token is shown to the user once, then encrypted into an expando value on the User object.
By using this expando value the UserLocalService-hook can authenticate the user thus enabling Liferay Sync to access user documents!
Webdav
Very related to Liferay sync is of course webdav. That is, a way to map a folder directly from your desktop (Document and Media Portlet happily informs you of this all the time) from different operating systems. There are a couple of drawbacks with webdav however, for one not all OS'es support the protocol entirely. For instance from a mac you're able to read documents but not upload new. From Windows 7 32bit it kind of works, but in 64 bits it doesn't. Or was it the other way around? Or was it with ipv6?
Anyway, lots of quirks. And! Authentication over webdav commonly use digest auth for authentication, there's support for this in Liferay but of course much more complex! It could probably be done, at least by copying source code, but given that the OS-support is very limited we're focusing on the Liferay Sync app instead.