SSO Infrastructure!

So, SSO is a big thing now. There's Auth0 as a hosted (and awesome) SSO provider, among others. Sadly, there aren't many open-source choices if you prefer to stay away from enterprise web-scale Java.

If you could care less about using web-scale Java, there's Shibboleth and other excellent solutions.

Personally, I don't want to have to deal with web-scale Java.

One of the plus-sides of Nginx is the fact that it is scriptable with Lua. Now, an SSO on top of Nginx has been done before. One of the first I found was SSOwat and then a Seatgeek/Chairnerd guide to SSOs inside Nginx.

SSOwat was awesome, but I had some issues with it. Configuration was a bit intense, the UI was built specifically for YunoHost, and there were some strange CDA problems. I spent lots of time modding the code to work for us, but it was tedious and hard to maintain.

So, I started writing my own solution.

Thus, LSSO was born. It sits right inside Nginx handling authentication between location directives. Cross-domain authentication is implemented and cookies will actually transfer across the SSO base domain to other domains also protected by the SSO.

Now, SSO handling is a little strange. I wanted to implement authentication against LDAP, but that adds in some interesting issues. How do we handle session expiry, scoping, etc..? Well, using OAuth simplifies a lot of this! With OAuth, we can request tokens that are valid for specific scopes, ensure that tokens are expired properly, etc. Next problem is finding an OAuth server that can use LDAP as a backend. With some searching, I found a bunch of "roll your own OAuth server" posts, but I didn't really want to do that considering I was already rolling SSO... Eventually, I found Osiris. Set it up in its own jail, hooked it up to LDAP, and started testing. Besides the Mongo-only token store connector, it was perfect! After some hardcore forking action, I had LDAP group-as-scope requests, multi-scope for LDAP group-as-scope, and a Redis token store. Suddenly, we had a solid backend.

Add time, frustration, blood, sweat, and tears and we've got the base for a decent SSO implementation without Java. The base SSO is all implemented in Lua. Auth portal is in HTML+CSS+JS since it only POSTs credentials to the SSO endpoint and displays error messages when needed. Redis is the storage backend for this, mainly because of speed, minimalism, and key expiry.

I'm extremely proud of LSSO, because through tons of normal usage and testing, it's been extremely resilient. I've got a huge roadmap of things to do to enhance LSSO. I am so excited to getting around to working extensively on this in the future.

Sean Johnson

Software developer, music enthusiast, college student, and cat lover. Currently enthralled by the world of networking, security, and cloud technology.

San Antonio, TX https://blog.maio.me

Subscribe to Land of Weird Things

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!