Authentication in Rails using mix-in’s

Posted by scientific on December 13, 2006


I downloaded Rails Recipes by Chad Fowler today and was playing with the authentication recipe (#31). I like the book overall, and it’s got some good nitty-gritty solutions which are easy to implement.

Recipe #31 in particular is very simple which is important for the book overall - it makes it easy to get started and expand as needed (which is exactly the steps I went through). I thought I would post some code that expands the tool slightly and makes it a “mix-in-able” module. Structured this way, now any AR class that wants the functionality, can simply “include” the mix-in and create two database fields, and it’s authentication enabled.. I also added a method called “password_matches?” which provides a convenient way to compare a plaintext password against the salt/hash version in table (which is why I refactored some of Chad Fowler’s methods too). It seemed like this method was helpful when receiving form posts with authentication data stored in plaintext from the user..

[for ActiveRecord model file]
  class User < ActiveRecord::Base
    include Models::Passwords
  end

[for a library file that the model file can "see"]:
  # module for including mix-ins for model classes
  module Models
    # provides hashed password capability for Models
    # Model which requires this module must have two fields: password_hash, password_salt
    module Passwords
      def password_salt
        super || gen_new_salt
      end

      def password=(plaintext_pass)
        # this line actually does something! if passsword_salt is not defined, this will create it for us
        self.password_salt = self.password_salt
        self.password_hash = gen_password_hash(plaintext_pass, self.password_salt)
      end

      def password_matches?(plaintext_password)
        self.password_hash == gen_password_hash(plaintext_password, self.password_salt)
      end

      private

      def gen_new_salt
        [Array.new(6){rand(256).chr}.join].pack(”m”).chomp
      end

      def gen_password_hash(plaintext_pass, salt)
        # code adapted from Rails Recipes v.1, p. 116
        Digest::SHA256.hexdigest(plaintext_pass + salt)
      end
    end
Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

Comments