ActiveResource and HTTP Basic Auth

I have a REST API that is HTTP Basic Auth enabled.

My user name is an email address: "email@domain.com" and my password is "asdf"

Logging in and everything work fine in the browser or curl. However, I'm lost at how to use an email for a username with ActiveResource. If I don't escape the '@' in the email I get a bad uri error:

URI::InvalidURIError: bad URI(is not URI?): http://email@domain.com:asdf@localhost:3000

and If I escape the '@' with '%40' it's taken literally and the username is passed to rails as 'email%40domain.com' and subsequently fails authentication.

class ARModel < ActiveResource::Base self.site = "http://email%40domain.com:asdf@localhost:3000" end

Any ideas what I should do?

CGI.unescape comes to mind. Not sure where that should be called, though, but CGI.unescape("%40") returns @.

I have the same problem and don't yet have a solution for you but observe that another REST client, the gem rally_rest_api (see rest_builder.rb #send_request), handles this by not relying on URI parsing. Instead they create a Net::HTTP::Get and then call #basic_auth username, password which set the credentials directly in the HTTP header. I haven't been successful in escaping the @ sign and suspect that it may be necessary to patch ActiveResource to behave like rest_builder.rb.

John-Mason Shackelford

Software Development Coach Pearson

2510 North Dodge St. Iowa City, IA 52245 ph. 319-354-9200x6214 john-mason.shackelford@pearson.com

I don't really have this issue anymore 'cause I moved to a token based auth system for my API. Regardless, I'm still thinking about filing a bug report in the rails trac, I'm just not sure if this is exceptional behavior or not...

This needs to be cleaned up so as not to break the previous behavior, but this is a hack that seems to work.

class ActiveResource::Connection

  def basic_auth_user=(username)     @basic_auth_user = username   end

  def basic_auth_pass=(password)     @basic_auth_pass = password   end

  def authorization_header     (@basic_auth_user || @basic_auth_pass ? { 'Authorization' => 'Basic ' + ["#{@basic_auth_user }:#{@basic_auth_pass}"].pack('m').delete("\r \n") } : {})   end

end

class ActiveResource::Base   # Pass username and password directly to the connection   # rather than on the URI so that we can add Basic Authorization headers   # for usernames which would not be permitted on the URI such as those in the   # of email addresses.   def self.auth_as(username,password)     self.connection.basic_auth_user = username     self.connection.basic_auth_pass = password   end end

class RallyResource < ActiveResource::Base   self.site = "https://rally1.rallydev.com:443/slm/webservice/1.05&quot;   self.auth_as 'myaddress@domain.com', 'secret' end

John-Mason Shackelford

Software Development Coach Pearson

2510 North Dodge St. Iowa City, IA 52245 ph. 319-354-9200x6214 john-mason.shackelford@pearson.com

Isn't this a cop-out of sorts? The uri-encoded text in the URI should be decoded shouldn't it?

A cop out? We're not out to win any awards... I personally think encoding it in the url is a bit ugly. You can use the #site attribute to set the userinfo (site is an instance of URI), but it falls for the same encoding problem. If someone wants to write a quick patch for URI, that'd be fine I suppose. But in the end, I went with something similar to what John proposed.

http://ar-code.svn.engineyard.com/lighthouse-api/lib/lighthouse.rb

Sorry, I didn't intend to sound so critical, but I thought it was just avoiding the issue.

Thanks for your link and thanks for your efforts John (above).

I'll take a look at these.

ALex

Ah, I was looking at your link.

Looks like ruby lighthouse API bindings using active resouce. I'll study this as I am doing the same thing for my API.