SeekingTruth
SeekingTruth

Reputation: 1054

Upgrade to rails 4.1.8 and my api broke

I haven't had the time to go through .6 and .7 as well as .8 in depth to make sure that I wasn't missing something, but today I decided to update my application, which is mostly an API with some front end work.

I updated the application to rails 4.1.8 and I got a lot of errors in my specs, in fact anything where the api had to be authenticated it blew up.

My controllers that use an api have a method called restrict_api_access which is done via

  def restrict_api_access
    authenticate_or_request_with_http_token do |token, options|
      @api_key = ApiKey.find_by(api_key: token)
    end unless current_user
  end

Now you can log into the app and manage things, in that case we still use the same API that you would access say via a terminal or out side app. so the unless current_user basically looks like like:

  def current_user
    if (@api_key)
      @current_user = User.find_by!(id: @api_key.xaaron_users_id)
    else
      super
    end
  end

Ans then the super of this current user basically states - are you logged in or not.

So one of the tests that are failing is set up like such:

context "Create new tag" do before(:each) do @tag = FactoryGirl.build(:tag, blog_id: @blog.id) set_auth_header(@user) end

it "should create a tag for a post" do
  post :create, :blog_id => @blog.id, tag: {name: @tag.name, description: 'asdasddsa'}
  json = JSON.parse(response.body)
  expect(json['tag']['name']).to eql @tag.name
end

end

@user is set up else where. But I can assure you that a user is being passed in and is created.

The other interesting method here is set_auth_header(@user) this method looks like:

# Create a random api key
def create_api_key(user)
  ApiKey.create!(:xaaron_users_id => user.id, :api_key => SecureRandom.hex(16))
end

# Set authentication headers for the API use
def set_auth_header(user)
  key = create_api_key(user)
  request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"
end

You can see we create an API key with the user, we then set the request environment variable to have that api key.

So before 4.1.8 (I was on 4.1.5) this worked fine, all my tests would pass life was grand. Now, with this particular test, I get:

  1) Api::V1::TagsController Create new tag should create a tag for a post
     Failure/Error: json = JSON.parse(response.body)
     JSON::ParserError:
       757: unexpected token at 'HTTP Token: Access denied.
       '
     # ./spec/controllers/api/v1/tags_controller_spec.rb:112:in `block (3 levels) in <top (required)>'

Essentially I am denied access. I have traced this through to the restrict_api_access to the line: authenticate_or_request_with_http_token which holds, as a value: HTTP Token: Access denied.

Is there something that changed in 4.1.8 that would be causing all my api that requires authentication to break?

Upvotes: 0

Views: 139

Answers (1)

Mark Przepiora
Mark Przepiora

Reputation: 171

You're computing your authorization header manually here, which might be wrong:

request.env['HTTP_AUTHORIZATION'] = "Token #{key.api_key}"

There's an ActionController method that does this for you:

request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(key.api_key)

Try that instead.

Upvotes: 1

Related Questions