I have two RSpec tests, a controller spec and a request spec, where I am making a GET request to the index action of the same controller. In both specs I am sending an Authorization header that contains an Oauth2 bearer token.
The problem I'm having is that depending on the type of spec, the header is stored on a different property of the request object. In the case of the request spec, it is available at request.env["Authorization"]
and in the case of the controller spec, it is available at request.session["Authorization"]
.
Why is "Authorization" stored in different places for different types of specs? Is there somewhere I can find it for both specs?
This bearer_token
method is in the parent controller class where I'm grabbing the token from the header:
Works with env
in the request specs:
def bearer_token
pattern = /^Bearer /
header = request.env["Authorization"] # <= env
header.gsub(pattern, '') if header && header.match(pattern)
end
Works with session
in the controller specs:
def bearer_token
pattern = /^Bearer /
header = request.session["Authorization"] # <= session
header.gsub(pattern, '') if header && header.match(pattern)
end
Here is my request spec:
describe '' do
let(:user) { Fabricate(:user) }
describe 'accessing content with valid token' do
let(:token) { OauthToken.create(user: user) }
let(:auth_headers) { {
'Authorization' => "Bearer #{token.access_token}",
'HTTPS' => 'on'
} }
before { get api_v2_cats_path, {}, auth_headers }
specify { response.status.should == 200 }
end
end
Here is my controller spec
describe Api::V2::CatsController do
let(:user) { Fabricate(:user) }
describe ".index" do
let(:token) { OauthToken.create(user: user) }
let(:auth_headers) { {
'Authorization' => "Bearer #{token.access_token}",
'HTTPS' => 'on'
} }
it "should be valid" do
get :index, { format: :json, page_size: 1 }, auth_headers
@json = JSON.parse(response.body)
@json.should_not be_nil
end
end
end
The HTTP Authorization request header can be used to provide credentials that authenticate a user agent with a server, allowing access to a protected resource. The Authorization header is usually, but not always, sent after the user agent first attempts to request a protected resource without credentials.
These can be stored in the browser local storage or session storage.
Here's how you can set the Authorization header, which is typically used to send access tokens to a server. // Send a GET request with the authorization header set to // the string 'my secret token' const res = await axios. get('https://httpbin.org/get', { headers: { authorization: 'my secret token' } });
I assumed that the API would be the same for the get
method between a request and controller spec. In the controller spec, the third argument is a hash of sessions variables, not header variables. You can set the headers directly on the @request
object like so:
describe Api::V2::CatsController do
let(:user) { Fabricate(:user) }
describe ".index" do
let(:token) { OauthToken.create(user: user) }
let(:auth_headers) { {
'Authorization' => "Bearer #{token.access_token}",
'HTTPS' => 'on'
} }
before do
@request.env.merge!(auth_headers)
end
it "should be valid" do
get :index, { format: :json, page_size: 1 }
@json = JSON.parse(response.body)
@json.should_not be_nil
end
end
end
Then the correct way to get the authorization header is using:
def bearer_token
pattern = /^Bearer /
header = request.env["Authorization"] # <= env
header.gsub(pattern, '') if header && header.match(pattern)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With