Why I roll my own authentication
» Posted on 2012-01-12This is what got me started writing this post:

In the Rails world, we are holding up the DRY principle high. One outcome of this is that people do put stuff that has to be done for many applications into gems, to be reused. Authentication is such a case, as you need authenticaton for nearly every web application you write. And devise seems to be the most mature and poplular solution in this regard. Yet I decided to roll my own authentication for my latest project. Why?
Well, first of all, I am trying to get rid of all external dependencies, wherever possible. In my last project, we used 161 (!!!) gems. It was not a crazily complex project, just a regular, larger web application. But each and every gem has to be added to the load path, slowing down each and every require statement throughout the application. The led to server startup times of 15 seconds and above, depending on the machine. To make things worse, this time was needed for every launch of the Rails console, for every single isolated test you would run. That is just too much wrench in the works for me, so I absolutely wanted to avoid this in my new project. So, no dependency if I do not absolutely need it.
The next point, however, is simple "graspability". We all know source
code is read far more often than written, so it should be easy for
fellow developers to grasp what is going on. And although I like the
devise source code, it is harder to grasp than code in your own
application. First of all, people have to run bundle open devise to
take look at the source. This is not really hard, but it is another
obstacle. Next, the devise code is far more abstract than your own code.
You can name your user model User, but you could also name it
ChemistryTeacher. The same is true for your Controllers. Devise can
handle that, which is great! But this flexibility comes at a price, and
that is the brainpower needed to understand how the code works. This
problem becomes worse, as soon as you want to change some of the
behaviour. Instead of just writing or adjusting the tests and
implementing your code, you must go to great lengths to to find out how
to hook into the existing gem code from your application. And the
result? Not very satisfying. Some of the behaviour is defined in the
gem, some in your application. Scattered in two places. Making
graspability even harder.
My last point of criticism is bloat. Devise is very powerful, and certainly offers stuff I do not need. I just want session management and password reset. Yet the code for all the other stuff devise has to offer is loaded into memory when I require the gem. While this is negligible for a single gem, memory consumption becomes insanely high for each Rails process when you are using 161 gems.
Luckily, Rails 3.1 was out when I started on the new project, and this
version introduced the
has_secure_password
method in ActiveModel. When I saw this in Ryan Bates
Railscast,
it immediately clicked. For me, that is the least common denominator,
the one thing that is the same for each and every application. I do not
need a gem to define my controllers, because I will want to change their
behaviour anyway, at some point of time. But what has_secure_password
does, that is the one thing I will need anywhere.
So I just ditched every authentication gem out there and just went to
write my own authenticaton. The process was smooth and easy, and in
about a day of purely test driven development, I had a nice and easy to
grasp authentication process inside my own application, with password
recovery and everything else I need. And as soon as I or anyone else on
the team wants to change the logic, she or he can just open their test
and app folders and go for it. So in my opinion, it is absolutely
worth trying.
So, what is your experience with authentication in Rails apps? Ever tried to roll your own? Would you do so in your next project?