What is a very simple authentication scheme for Sinatra/Rack

AndrewVos picture AndrewVos · Aug 24, 2010 · Viewed 28.9k times · Source

I am busy porting a very small web app from ASP.NET MVC 2 to Ruby/Sinatra.

In the MVC app, FormsAuthentication.SetAuthCookie was being used to set a persistent cookie when the users login was validated correctly against the database.

I was wondering what the equivalent of Forms Authentication would be in Sinatra? All the authentication frameworks seem very bulky and not really what I'm looking for.

Answer

Todd Yandell picture Todd Yandell · Aug 24, 2010

Here is a very simple authentication scheme for Sinatra.

I’ll explain how it works below.

class App < Sinatra::Base
  set :sessions => true

  register do
    def auth (type)
      condition do
        redirect "/login" unless send("is_#{type}?")
      end
    end
  end

  helpers do
    def is_user?
      @user != nil
    end
  end

  before do
    @user = User.get(session[:user_id])
  end

  get "/" do
    "Hello, anonymous."
  end

  get "/protected", :auth => :user do
    "Hello, #{@user.name}."
  end

  post "/login" do
    session[:user_id] = User.authenticate(params).id
  end

  get "/logout" do
    session[:user_id] = nil
  end
end

For any route you want to protect, add the :auth => :user condition to it, as in the /protected example above. That will call the auth method, which adds a condition to the route via condition.

The condition calls the is_user? method, which has been defined as a helper. The method should return true or false depending on whether the session contains a valid account id. (Calling helpers dynamically like this makes it simple to add other types of users with different privileges.)

Finally, the before handler sets up a @user instance variable for every request for things like displaying the user’s name at the top of each page. You can also use the is_user? helper in your views to determine if the user is logged in.