Note

This is not anywhere near done. It's still using swaths of code just copied straight over from merb, and even some of that doesn't do anything yet.

Install

Add config.gem 'myobie-rails-auth', :lib => 'rails-auth', :source => 'http://gems.github.com' to your environment.rb file. Then rake gems:install or just install it yourself.

About

I am not satisfied with any of the current authentication strategies available for rails. I am sure Rails 3 will have something built in, but until then this is what I am going to use. I am spoiled from the way Merb does it, but even then I am not 100% happy with how it works.

Currently, this is untested and very much a copy of how merb does it. However, I am using it in production.

All I really care about:

  • Authenticate the session
  • Authentication strategies
  • Let me use my own model how I want
  • Let me do my own controller how I want
  • Be easy to setup (as an initializer)
  • Don't do anything magical

I hate how all the authentication libraries hide model, controller, view methods from you down in the gem file. I also hate the generators that are impossible to use to update from one version to the next.

In my mind, the best way to solve this is to not have a ton of necessary methods on anything.

All you should need

  1. UserModel#authenticate
  2. Use ensure_authenticated in your controller to make sure they are logged in.
  3. rescue_from Rails::Authentication::Unauthenticated to catch when they are not logged in.
  4. Setup an initializer that sets the UserModel class, etc

Simple.

Usage

After you have installed the gem, you will need to use it in the manner you see fit. I have created some examples (look in examples/ inside the gem) that come straight from how I use it right now. These are not generators.

Initializer (authentication.rb)

I'll just go through the file in order. First I activate the strategies that I want (you can create/activate your own here too), then set my user model class. Then I tell Rails::Authentication how to store/fetch a user from the session (by id) and which session keys to keep during login/logout (like the return to url, don't want to loose that). Then I just require all available helpers and set two constants that I use in my user model to encrypt passwords.

I marked what is optional/required.

ApplicationController

Simple Example

The easiest way to get up and running is to include the ensure_authenticated helper in ApplicationController and then decide what you want to do when the Rails::Authentication::Unauthenticated error is raised.

Complex Example

There are some helpers you can include along with the ensure_authenticated helper by including Rails::AuthenticatedControllerExtensions. You will find helpers for remember me cookies, setting a return to url to redirect to after login, logged in? and other helpers resembling restful-authentication, and a helper for setting a custom flash message when the user is not logged in. See the [rails-auth/helpers][helpers] folder.

SessionsController

You don't have to create a SessionsController at all, but I like the idea of creating/destroying a session when logging in/out.

Simple Example

The ensure_authenticated helper will do the login if the correct params are present (if they are submitted from a form, basic http auth, etc). So really, all you need to do is use that method.

Complex Example

This example uses before_filters to order method calls in the correct order each time. It keeps track of certain session data that we never want to use (like the return to url) and also handles a remember me checkbox. It really is essentially the same as the simple example, but with a ton of methods around the core action code.

User (model)

Simple Example

All you need in your model (for the password_form strategy) is self.authenticate. It can look however you want, but I have provided an example that you may not want to use, since the passwords are not encrypted.

Complex Example

I'll try to hit the highlights, but essentially we aren't actually saving the password, but saving a crypted_password instead. This example needs some more love and I should include my user_mailer as well. I will update this example soon.

I put some validations to show that there are some regex's in the gem (although I am considering moving them out). Then you will see activate! which activates a user (I send activation emails out). The authenticate method is still pretty simple, except it delegates to an authenticated? instance method on the user to do it's work.

There is a lot of digest and other crap that encrypts the passwords. We save an encrypted version of the password in the db, then when the user types their password into the form field, we encrypt what they typed and compare it to the encrypted form in the db (they should be the same since it supposedly was the same word that was encrypted both times).

There is also some remember/forget stuff in there.

TODO

  • Tests
  • Remove Mash
  • Decide if the status, body, etc should be set by the authentication gem or not (right now it's kinda both)