As our rails apps multiply, we began looking for a single-sign-on solution - to give some sense of a seamless 'application' to our users. We've picked rubyCAS for this as it's pretty much the only single sign-on solution that's already out there and running for ruby (and comes with both a server and client gem already written, which is handy).
We'd been running restful_authentication on our main app, and so our new CAS setup had to be able to handle all the existing stories before it was acceptable as an alternative. Over the next few articles, I'll share some of the more useful little snippets I came up with.
In a nutshell?
CAS is a protocol for Authentication. It is not exclusive to ruby, but the ruby-implementation consists of two halves: the server and client.
The server is an independent 'camping' application (ie rack-style ruby). The client is a gem/plugin that fits inside each of the applications that we are writing. The client has the code that allows us to use the rubyCAS-server as an authentication method. Most of the rest of the articles will deal with using the client.
How the two talk to each other is pretty complex, and most of it is beyond the scope of this article... and mostly you don't need to know the details to get it all working. Again, in a nutshell:
Users that try to hit one of our applications will be passed over to the rubycas-server for authentication which has a login form. They type in their login details. If this matches what's in our system, then they will be given a one-time ticket and sent back to the application they started at. The application will verify this ticket with the server, and get a proper ticket and put it into a cookie that will then allow them to be continually authenticated with that application from then on.
The single-sign-on part comes from when the user tries to then access one of the other applications running rubycas-client. The new app will see the user has the cookie, and send it back to the rubycas-server.. but gets redirected back to the new app before they get actually shown the login page with a new "it's ok, we know this guy" ticket. The new app sees this ticket and now user will be automatically logged into the other application as well.
If the user clicks logout, the app destroys it's own session, and sends the user to the rubycas-server logout page... which also destroys the ticket in its own database.
That's how it all hangs together.
If you really have a burning need to know more details, go check out the rubyCAS-server documentation which has full workflows.
So what do we want?
As I said, we're re-implementing the authentication that we had as restful_authentication... so we need to implement all the features we had there... but also single-sign-on to our new applications. What follows is a minimal wishlist for replacing existing functionality:
- Filter and Login action that populates local user (eg current_user)
- a logged_in? function usable for greetings and displaying the right login/logout buttons
- Logout action
- filter for pages that sometimes require login (ie the GatewayFilter)
- Using a form to post login-credentials to CAS (so you can put a login-box on your signup page)
- admin_login_required (access restriction before_filter making actions admin-only)
- Auto-login after create (so your newly-registered user doesn't have to retype the login credentials they just gave you)
- Redirection of root_url to a special page (eg dashboard) if the user is already logged-in without breaking all of the above
- Authorisation (eg user roles)
- Single sign-out (the issues and why we didn't...)
I probably won't tackle them in order... but should get to all of them eventually.