Chowder is a Sinatra-based Rack middleware providing easy session based authentication. You can put Chowder in front of all your other Rack based apps to provide a single authentication mechanism for a multitude of apps.
Chowder consists of two parts:
- Chowder::Basic providing 'old school' login.
- Chowder::OpenID providing .. eh, take a guess.
Both authentication mechanisms provide these URLs:
GET /login
Provides a basic login form.
GET /logout
Logs out the user by setting 'current_user' session key to nil/false.
Additionally Chowder::Basic
provides:
POST /login
Takes 'login' and 'password' params.
Upon successful login the session key 'current_user' is set to whatever
the block you provide the Chowder middleware with returns and the user is
redirected to whatever path is set in the 'redirect_to' session key or '/'
if not set. If login fails, the user is redirected to '/login' and the
'current_user' session key is nil or false.
GET /signup
Provides a basic signup form.
This is only available if you have provided a :signup function to Chowder::Basic.
POST /signup
Takes whatever params are on the form ('login' and 'password' by
default) and passes them, as a hash, to your :signup callback.
About the signup callback:
Your signup callback has to return one of two things:
If you successfully sign up a user (whatever that means for you),
your callback must return a two-element array like so:
[true, newuser.id]
.
If there were errors, your signup callback must return an n-element
array like so:
[false, "error 1", "error 2", ...]
.
These errors will be made available to your custom signup view as @errors
.
And Chowder::OpenID
provides:
POST /openid/initiate
GET /openid/authenticate
Chowder ships with a bunch of Sinatra helpers (although you can (and should) use Chowder with all Rack based apps) to make life that lil' bit easier:
require 'chowder'
require 'chowder/openid'
require 'my_app'
use Chowder::Basic,
:login => lambda {|login, password|
user = User.first(:login => login , :password => password) and user.id
},
:signup => lambda {|params|
# DataMapper style; of course you can do ActiveRecord or whatever
u = User.create(params)
if u.valid?
[true, u.id]
else
[false, *(u.errors)]
end
}
use Chowder::OpenID do |url|
user = User.first(:openid => url) and user.id
end
run Sinatra::Application
require 'sinatra'
require 'sinatra/chowder'
get '/' do
'This is public'
end
get '/admin' do
require_user
'This is private'
end
I recommend just storing something like user ID in the session cookie and
overriding the current_user
helper to return the user form your DB or
whatevz:
helpers do
def current_user
User.first(session[:current_user])
end
end
current_user
, authorized?
, login
, logout
, require_user
.
Using Chowder with Rails is easy. First, add Chowder to your gem dependencies
and middleware stack in config/environment.rb
:
config.gem 'chowder'
config.gem 'chowder', :lib => 'chowder/rails'
config.middleware.use Chowder::Basic do |user,pwd|
user == "foo" && pwd == "bar"
end
Next include Chowder::Rails
in your controllers to get a bunch of
Chowder-related helpers, and use require_user
to protect your application:
class ApplicationController < ActionController::Base
include Chowder::Rails
before_filter :require_user, :only => [:secret1, :secret2]
...
end
Rails doesn't behave exactly like Rack::Builder
, so a small hack is required
to make Chowder work with Rails, you can place this in config/environment.rb
:
class Chowder::Basic
def self.call(*args)
args.empty? ? self : super(*args)
end
end
This has been fixed in Rails edge.
current_user
, authorized?
, login
, logout
, require_user
.
The default login view is quite dull, but if you have either views/login.haml or views/login.erb, that'll be rendered instead. A custom login view must have a form sending a POST request to /login with 'login' and 'password' parameters.
Likewise, the default signup view is overridden if you have views/signup.haml or views/signup.erb. It needs the same 'login' and 'password' parameters as the login form. You can do whatever fancy stuff you like; all your form params get passed right to your :signup callback.
If you provide a value for the :secret
-key, the cookie data will be
checked for data integrity, courtesy of Rack::Session::Cookie
.
Copyright (c) 2009 Harry Vangberg [email protected] Sam Merritt http://github.com/smerritt/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.