Search code examples
rubyforms-authenticationsinatra

What is a very simple authentication scheme for Sinatra/Rack


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.


Solution

  • 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.