Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec Request - How to set http authorization header for all requests

I'm using rspec request to test a JSON API that requires an api-key in the header of each request.

I know I can do this:

get "/v1/users/janedoe.json", {}, { 'HTTP_AUTHORIZATION'=>"Token token=\"mytoken\"" }

But it is tedious to do that for each request.

I've tried setting request.env in the before block, but I get the no method NilClass error since request doesn't exist.

I need some way, maybe in the spec-helper, to globally get this header sent with all requests.

like image 863
Buzz Avatar asked Oct 06 '12 16:10

Buzz


People also ask

How do I add authorization header in GET request?

To send a GET request with a Bearer Token authorization header, you need to make an HTTP GET request and provide your Bearer Token with the Authorization: Bearer {token} HTTP header.

How do I send the authorization header in HTTP?

It is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization header that contains the word Basic, followed by a space and a base64-encoded(non-encrypted) string username: password. For example, to authorize as username / Pa$$w0rd the client would send.

How do I request a post with authorization header?

To send a request with the Bearer Token authorization header, you need to make an HTTP request and provide your Bearer Token with the "Authorization: Bearer {token}" header. A Bearer Token is a cryptic string typically generated by the server in response to a login request.


1 Answers

To set it in a before hook you need to access it like

config.before(:each) do
  controller.request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials('mytoken')
end

I too hated the giant hash, but preferred to be explicit in authorizing the user in different steps. After all, it's a pretty critical portion, and . So my solution was:

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate user
    token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
    request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
  end
end

#spec/spec_helper.rb
RSpec.configure do |config|
  ...
  config.include ControllerSpecHelpers, :type => :controller

then I can use it like so

describe Api::V1::Users, type: :controller do
  it 'retrieves the user' do
    user = create :user, name: "Jane Doe"
    authorize user
    get '/v1/users/janedoe.json'
  end
end

I find this great for testing different authorization levels. Alternatively, you could have the helper method spec out the authorize function and get the same result, like so

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate
    controller.stub(:authenticate! => true)
  end
end

However, for ultimate speed and control, you can combine them

#spec/helpers/controller_spec_helpers.rb
module ControllerSpecHelpers
  def authenticate user = nil
    if user
      token = Token.where(user_id: user.id).first || Factory.create(:token, user_id: user.id)
      request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token.hex)
    else
      controller.stub(:authenticate! => true)
    end
  end
end

and then authorize entire blocks with

#spec/spec_helper.rb
...
RSpec.configure do |config|
  ...
  config.before(:each, auth: :skip) { authenticate }

#**/*_spec.rb
describe Api::V1::Users, type: :controller do
  context 'authorized', auth: :skip do
    ...
like image 111
cadlac Avatar answered Nov 02 '22 00:11

cadlac