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
http://pearsonschool.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"
  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
http://pearsonschool.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.