Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Minimalistic authentication plugin for Rails 3 apps
Branch: master
Pull request Compare This branch is 13 commits ahead, 2 commits behind GBH:master.
Failed to load latest commit information.
lib Flags STI error
.gitignore ignoring gemfile.lock
.travis.yml now it's possibe to override session class
Gemfile Flags error if model has not been included in the initializer list (S…
LICENSE squishing everything Documentation edit.
Rakefile some docs
VERSION Version bump to 0.1.4
letmein.gemspec Regenerate gemspec for version 0.1.4

letmein Build Status

letmein is a minimalistic authentication plugin for Rails 3 applications. It doesn't have anything other than the UserSession (or WhateverSession) object that you can use to authenticate logins.


Plug the thing below into Gemfile and you know what to do after.

gem 'letmein'

If you want to authenticate User with database fields email, password_hash and password_salt you don't need to do anything. If you're authenticating something else, you want something like this in your initializers:

LetMeIn.configure do |conf|
  conf.model      = 'Account'
  conf.attribute  = 'username'
  conf.password   = 'password_crypt'
  conf.salt       = 'salty_salt'

When creating/updating a record you have access to password accessor.

>> user = => '', :password => 'letmein')
=> true
>> user.password_hash 
=> $2a$10$0MeSaaE3I7.0FQ5ZDcKPJeD1.FzqkcOZfEKNZ/DNN.w8xOwuFdBCm
>> user.password_salt
=> $2a$10$0MeSaaE3I7.0FQ5ZDcKPJe


You authenticate using UserSession object. Example:

>> session = => '', :password => 'letmein')
=> true
>> session.user
=> #<User id: 1, email: "" ... >

When credentials are invalid:

>> session = => '', :password => 'bad_password')
=> false
>> session.user
=> nil


There are no built-in routes/controllers/views/helpers or anything. I'm confident you can do those yourself, because you're awesome. But here's an example how you can implement the controller handling the login:

class SessionsController < ApplicationController
  def create
    @session =[:user_session])!
    session[:user_id] =
    flash[:notice] = "Welcome back #{}!"
    redirect_to '/'

  rescue LetMeIn::Error[:error] = 'Invalid Credentials'
    render :action => :new

Upon successful login you have access to session[:user_id]. The rest is up to you.

Authenticating Multiple Models

Yes, you can do that too. Let's assume you also want to authenticate admins that don't have email addresses, but have usernames.

LetMeIn.configure do |conf|
  conf.models     = ['User', 'Admin']
  conf.attributes = ['email', 'username']

Bam! You're done. Now you have an AdminSession object that will use username and password to authenticate.

Token-Based Authentication

Token authentication provides a simple solution for exposing APIs. When enabled, Letmein will automatically generate a token (40 character hex) for each new user. Instead of passing email and password to the UserSession, you merely pass auth_token. To enable tokens:

LetMeIn.configure do |conf|
  conf.generate_token = true

Its usage differs from the email/password combo in only one way:

@session = => "258082e5588dea110592154f48ef1e309a8bbff5")

This will successfully (or not) authenticate you with the token above.

Overriding Session Authentication

By default user will be logged in if provided email and password match. If you need to add a bit more logic to that you'll need to create your own session object. In the following example we do an additional check to see if user is 'approved' before letting him in.

class MySession < LetMeIn::Session
  # Model that is being authenticated is derived from the class name
  # If you're authenticating multiple models you need to specify which one
  @model = 'User'

  def authenticate
    super # need to authenticate with email/password first
    unless user && user.is_approved?
      # adding a validation error will prevent login
      errors.add :base, "You are not approved yet, #{}."


(c) 2011 Oleg Khabarov, released under the MIT license

Something went wrong with that request. Please try again.