10.19.06
Authentication for your API or Feed
by Chris Abad
Getting authentication for your your API or your RSS /Atom feed is a lot simpler than you might think. Long story short, restful_authentication will default to act like HTTP Basic Auth for xml requests. Its just a small step from there to get the same functionality for your RSS feeds.
I’ve always liked acts_as_authenticated for my authentication needs. restful_authentication is simply a more “RESTful” version of this plugin. When I realized I could continue using this same authentication system for all my authentication needs, I knew I had a winner.
Enough talking, let’s jump in! Start off by installing the simply_restful plugin:
script/plugin install -x http://svn.techno-weenie.net/projects/plugins/restful_authentication
Follow the README to get the plugin up and running. We’ll start off with an easy one. Let’s look at adding authentication to our REST API . Be sure to require authentication your controller:
before_filter :login_required
That’s more or less it. Here’s where the magic happens (you’ll find this in lib/authenticated_system.rb):
def login_required username, passwd = get_auth_data self.current_user ||= User.authenticate(username, passwd, current_subdomain) || :false if username && passwd logged_in? && authorized? ? true : access_denied end def get_auth_data user, pass = nil, nil # extract authorisation credentials if request.env.has_key? 'X-HTTP_AUTHORIZATION' # try to get it where mod_rewrite might have put it authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split elsif request.env.has_key? 'HTTP_AUTHORIZATION' # this is the regular location authdata = request.env['HTTP_AUTHORIZATION'].to_s.split end # at the moment we only support basic authentication if authdata && authdata[0] == 'Basic' user, pass = Base64.decode64(authdata[1]).split(':')[0..1] end return [user, pass] end def access_denied respond_to do |accepts| accepts.html do store_location redirect_to :controller => '/sessions', :action => 'new' end accepts.xml do headers["Status"] = "Unauthorized" headers["WWW-Authenticate"] = %(Basic realm="Outlandish API") render :text => "Could't authenticate you", :status => '401 Unauthorized' end end false end
What this does have your login_required before_filter re-grab your login/password if its available via HTTP Basic Auth. If you try to login through XML and you’re denied, it’ll return the proper 401 Unauthorized status.
Adding the same authentication functionality to your RSS feeds is pretty simple. The only change you need to make is to make sure that the proper status is returned for your RSS requests if the login fails. Just modify the access_denied method:
def access_denied respond_to do |accepts| accepts.html do store_location redirect_to :controller => '/sessions', :action => 'new' end accepts.xml do headers["Status"] = "Unauthorized" headers["WWW-Authenticate"] = %(Basic realm="Outlandish API") render :text => "Could't authenticate you", :status => '401 Unauthorized' end accepts.rss do headers["Status"] = "Unauthorized" headers["WWW-Authenticate"] = %(Basic realm="Outlandish RSS Feed") render :text => "Could't authenticate you", :status => '401 Unauthorized' end end false end
There you go, that takes care of it. Simple Basic HTTP Auth for your API and feed, all mixed in with the authentication goodness the rest of your app gets with restful_authentication.
Comments
There are no comments.
Leave a Comment