HTTP Basic Authentication using restful_authentication with Rails 1.2
I ran into a small issue this morning with the restful_authentication plugin. We are developing an application where we need to provide a JSON data feed. The feed is protected using HTTP Basic Authentication. There is currently a bug in the plugin which makes Basic Authentication fail. When using the following curl command, I kept receiving a 406 http code from the server.
curl -X GET --basic -u bcurren:test http://localhost:3000/accounts.js
The reason for the 406 error was two fold: 1. there was a bug in restful_authentication which rejects all username and password combinations, even if they are valid 2. restful_authentication does not respond to js requests, so a 406 error is returned, meaning the request type is not valid.
To fix the bug in restful_authentication, I changed the following:
def login_required self.current_user ||= User.authenticate(username, passwd) || :false if username && passwd logged_in? && authorized? ? true : access_denied end
to the following
def login_required if self.current_user == :false && username && passwd self.current_user = User.authenticate(username, passwd) || :false end logged_in? && authorized? ? true : access_denied end
The bug is a result of :false being returned from current_user rather than false or nil. Since :false is a symbol it always evaluates to true when used in conditions. The updated code explicitly test if the current_user == :false
After the bug fix above, I was able to successfully retrieve the JSON feed when supplying a valid username and password. However, when submitting and invalid username and password, the application was return a 406 code rather than a 401. This does not result from a bug in restful_authentication but from a lack of support for js requests out of the box. I simply added the following to the access_deniedmethod in authentication_system.rb.
accepts.js do headers["Status"] = "Unauthorized" headers["WWW-Authenticate"] = %(Basic realm="Web Password") render :text => "Could't authenticate you", :status => '401 Unauthorized' end
I hope this post helps anyone who is tackling the similar issue in Rails 1.2. I will post about some of the other trail and tribulations of using the to_json method in Rails 1.2 in the near future.