-
Notifications
You must be signed in to change notification settings - Fork 204
Strategies
Warden uses the concept of cascading strategies to determine if a request should be authenticated. Warden will try strategies one after another until either,
- One succeeds
- No Strategies are found relevant
- A strategy Fails
Conceptually a strategy is where you put the logic for authenticating a request. Practically it's a descendant of Warden::Strategies::Base
.
Many strategies can be defined and selectively used.
Lets take a look at defining one:
Warden::Strategies.add(:password) do
def valid?
params['username'] || params['password']
end
def authenticate!
u = User.authenticate(params['username'], params['password'])
u.nil? ? fail!("Could not log in") : success!(u)
end
end
This declares a strategy called :password. The two things to note are the #authenticate!
and #valid?
methods.
The valid?
method acts as a guard for the strategy. It's optional to declare a valid?
method, and if you don't declare it, the strategy will always be run. If you do declare it though, the strategy will only be tried if #valid?
evaluates to true.
The strategy above is reasoning that if there's either a 'username'
or a 'password'
param, then the user is trying to login. If there's only one of them, then the User.authenticate
call will fail, but it was still the desired (valid) strategy.
This is where the work of actually authenticating the request steps in. Here's where the logic for authenticating your requests occurs.
You have a number of request related methods available.
-
request
- Rack::Request object -
session
- The session object for the request -
params
- The parameters of the request -
env
- The Rack env object
There are also a number of actions you can take in your strategy.
-
halt!
- halts cascading of strategies. Makes this one the last one processed. -
pass
- ignore this strategy. It is not required to call this and this is only sugar. -
success!
- Supplysuccess!
with a user object to log in a user. Causes ahalt!
. -
fail!
- Sets the strategy to fail. Causes ahalt!
. -
redirect!
- redirect to another url. You can supply it with params to be encoded and also options. Causes ahalt!
. -
custom!
- return a custom rack array to be handed back untouched. Causes ahalt!
.
There are a couple of misc things to do, too:
-
headers
- set headers to respond with relevant to the strategy. -
errors
- provides access to an errors object. Here you can put in errors relating to authentication.
To use a strategy, refer to it via the label that it was given when it was declared:
env['warden'].authenticate(:password)
to use the :password
strategy. You can use multiple strategies, and each one will be tried in order until either one is halted or none have been.
env['warden'].authenticate(:password, :basic)
This will use the :password
, and failing that, the :basic
strategies.
It is possible to share strategies with any other application that uses Warden. The benefit from doing this of course depends on your individual situation.
For some things like OpenID, Facebook or Google, a strategy may be useful to share if they're flexible. However, this kind of community sharing may not fit your needs exactly. Good strategies can be written and hopefully there will be many that come to light.
Declaring a strategy has been made as simple as possible whilst remaining flexible.
The most obvious wins to be had from sharing strategies between application instances are by multiple applications run by the same company. Many small applications can all be given the same authentication. For example, you may want to throw up a quick test application in Sinatra or straight Rack. Using Warden you can share the same strategies from your main application and provide consistent, company-wide authentication requirements.