Skip to content

Simple Rails Oauth Functional & Integration Testing

We are (UserVoice that is) about to release a new api that is based on a combination of 2-legged and 3-legged oauth. While checking the functional tests that had been written I noticed that they contained a lot of mocked methods, which while not a bad thing in itself, in this case meant a lot of functionality (specifically authorization) was not being checked.

So, I had a poke about in the gem (Oauth (0.3.6)) and wrote a couple of helper methods to allow for testing oauth based requests without mocking too much out, or in the case of integration tests, mocking nothing.


First off add this to your test_helper

include OAuth::Helper

# Functional test helpers
def oauth_helper_for_client(client)
  # gonna do everything but actually create a sig, cause its a pain
  OAuth::Signature::HMAC::SHA1.any_instance.stubs(:==).returns(true)
  OAuth::Client::Helper.new(@request, {:consumer => client})
end

def oauth_helper_for_client_and_user(client, user)
  token = AccessToken.find_or_create_by_user_id_and_client_id(user.id, client.id)
  OAuth::Signature::HMAC::SHA1.any_instance.stubs(:==).returns(true)
  OAuth::Client::Helper.new(@request, {:consumer => client, :token => token})
end

# Integration test helper
def oauth_header_for_method_uri_client_user_and_params(method, uri, client, user, params={})
  token = AccessToken.find_or_create_by_user_id_and_client_id(user.id, client.id)
  request = OAuth::RequestProxy.proxy(
     "method"       => method,
     "uri"               => uri,
     "parameters" => {
       "oauth_consumer_key"       => client.key,
       "oauth_token"                     => token.token,
       "oauth_signature_method" => "HMAC-SHA1",
       "oauth_timestamp"             => generate_timestamp,
       "oauth_nonce"                    => generate_nonce,
       "oauth_version"                  => '1.0'
     }.merge(params).reject { |k,v| v.to_s == "" }
  )

  signature = OAuth::Signature.sign request,
    :consumer_secret => client.secret,
    :token_secret       => token.secret

  request.parameters["oauth_signature"] = signature
  request.oauth_header
end

This gives you 3 new helper methods. The first can be used in functional tests to create a 2-legged oauth request and the second to create a 3-legged oauth as so:

def test_index_xml
  get :index, {:format => 'xml'}.merge(oauth_helper_for_client(clients(:some_consumer)).oauth_parameters)
  assert_response :success
end

The third method (which actually should have a parallel no user version for 2-legged, but that is left as an exercise for the reader..) allows you to simply create a fully signed request as shown below:

[NB. that the parameters are passed as strings not symbols, the Oauth library is not so happy with symbols]

post( url, { :value => value }, {
  'Accept'=> 'application/json', 'Authorization' => oauth_header_for_method_uri_client_user_and_params(
    "POST", URI.parse(url), clients(:uservoice),users(:scott),{"value" => value}
  )
})

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*