使用 RSpec 请求规范授权请求时无效 access_token
Invalid access_token when using RSpec request specs to authorize a request
我正在尝试测试 CredentialsController
,它在生产中运行良好,使用 RSpec 请求规范。
代码
控制器
class CredentialsController < ApplicationController
before_action :doorkeeper_authorize!
def me
render json: current_user
end
end
(GET /me
路由到 CredentialsController#me
。)
请求规格
describe 'Credentials', type: :request do
context 'unauthorized' do
it "should 401" do
get '/me'
expect(response).to have_http_status(:unauthorized)
end
end
context 'authorized' do
let!(:application) { FactoryBot.create(:application) }
let!(:user) { FactoryBot.create(:user) }
let!(:token) { FactoryBot.create(:access_token, application: application, resource_owner_id: user.id) }
it 'succeeds' do
get '/me', params: {}, headers: {access_token: token.token}
expect(response).to be_successful
end
end
end
未授权测试通过,但授权测试未通过:
expected #<ActionDispatch::TestResponse:0x00007fd339411248 @mon_mutex=#<Thread::Mutex:0x00007fd339410438>, @mo..., @method=nil, @request_method=nil, @remote_ip=nil, @original_fullpath=nil, @fullpath=nil, @ip=nil>>.successful?
to return true, got false
headers 表示令牌有问题:
0> response.headers['WWW-Authenticate']
=> "Bearer realm=\"Doorkeeper\", error=\"invalid_token\", error_description=\"The access token is invalid\""
token
我觉得还行,不过:
0> token
=> #<Doorkeeper::AccessToken id: 7, resource_owner_id: 8, application_id: 7, token: "mnJh2wJeEEDe0G-ukNIZ6oupKQ7StxJqKPssjZTWeAk", refresh_token: nil, expires_in: 7200, revoked_at: nil, created_at: "2020-03-19 20:17:26", scopes: "public", previous_refresh_token: "">
0> token.acceptable?(Doorkeeper.config.default_scopes)
=> true
工厂
访问令牌
FactoryBot.define do
factory :access_token, class: "Doorkeeper::AccessToken" do
application
expires_in { 2.hours }
scopes { "public" }
end
end
申请
FactoryBot.define do
factory :application, class: "Doorkeeper::Application" do
sequence(:name) { |n| "Project #{n}" }
sequence(:redirect_uri) { |n| "https://example#{n}.com" }
end
end
用户
FactoryBot.define do
factory :user do
sequence(:email) { |n| "email#{n}@example.com" }
password { "test123" }
password_confirmation { "test123" }
end
end
问题
- 为什么我收到此请求
invalid_token
?
- 我的 Doorkeeper 工厂看起来正确吗?
我传递的令牌有误。而不是:
get '/me', params: {}, headers: {access_token: token.token}
我必须使用:
get '/me', params: {}, headers: { 'Authorization': 'Bearer ' + token.token}
你可以检查你的 Access Token 工厂的作用域,它应该和初始化器的 default_scopes
一样
例如
config/initializers/doorkeeper.rb
default_scopes :read
下面,您的访问令牌工厂的范围应该是
factory :access_token, class: "Doorkeeper::AccessToken" do
sequence(:resource_owner_id) { |n| n }
application
expires_in { 2.hours }
scopes { "read" }
end
此外,如果您遇到响应状态:406 而 get '/me'....
表示不支持请求的格式(默认HTML)。您也可以在 HTTP header.
中发送 Accept="application/json" 而不是 '.json'
get '/me', params: {}, headers: {
'Authorization': 'Bearer ' + token.token,
'Accept': 'application/json'}
我用这个方法解决了我的问题,也许你可以试试。
我正在尝试测试 CredentialsController
,它在生产中运行良好,使用 RSpec 请求规范。
代码
控制器
class CredentialsController < ApplicationController
before_action :doorkeeper_authorize!
def me
render json: current_user
end
end
(GET /me
路由到 CredentialsController#me
。)
请求规格
describe 'Credentials', type: :request do
context 'unauthorized' do
it "should 401" do
get '/me'
expect(response).to have_http_status(:unauthorized)
end
end
context 'authorized' do
let!(:application) { FactoryBot.create(:application) }
let!(:user) { FactoryBot.create(:user) }
let!(:token) { FactoryBot.create(:access_token, application: application, resource_owner_id: user.id) }
it 'succeeds' do
get '/me', params: {}, headers: {access_token: token.token}
expect(response).to be_successful
end
end
end
未授权测试通过,但授权测试未通过:
expected
#<ActionDispatch::TestResponse:0x00007fd339411248 @mon_mutex=#<Thread::Mutex:0x00007fd339410438>, @mo..., @method=nil, @request_method=nil, @remote_ip=nil, @original_fullpath=nil, @fullpath=nil, @ip=nil>>.successful?
to return true, got false
headers 表示令牌有问题:
0> response.headers['WWW-Authenticate']
=> "Bearer realm=\"Doorkeeper\", error=\"invalid_token\", error_description=\"The access token is invalid\""
token
我觉得还行,不过:
0> token
=> #<Doorkeeper::AccessToken id: 7, resource_owner_id: 8, application_id: 7, token: "mnJh2wJeEEDe0G-ukNIZ6oupKQ7StxJqKPssjZTWeAk", refresh_token: nil, expires_in: 7200, revoked_at: nil, created_at: "2020-03-19 20:17:26", scopes: "public", previous_refresh_token: "">
0> token.acceptable?(Doorkeeper.config.default_scopes)
=> true
工厂
访问令牌
FactoryBot.define do
factory :access_token, class: "Doorkeeper::AccessToken" do
application
expires_in { 2.hours }
scopes { "public" }
end
end
申请
FactoryBot.define do
factory :application, class: "Doorkeeper::Application" do
sequence(:name) { |n| "Project #{n}" }
sequence(:redirect_uri) { |n| "https://example#{n}.com" }
end
end
用户
FactoryBot.define do
factory :user do
sequence(:email) { |n| "email#{n}@example.com" }
password { "test123" }
password_confirmation { "test123" }
end
end
问题
- 为什么我收到此请求
invalid_token
? - 我的 Doorkeeper 工厂看起来正确吗?
我传递的令牌有误。而不是:
get '/me', params: {}, headers: {access_token: token.token}
我必须使用:
get '/me', params: {}, headers: { 'Authorization': 'Bearer ' + token.token}
你可以检查你的 Access Token 工厂的作用域,它应该和初始化器的 default_scopes
例如
config/initializers/doorkeeper.rb
default_scopes :read
下面,您的访问令牌工厂的范围应该是
factory :access_token, class: "Doorkeeper::AccessToken" do
sequence(:resource_owner_id) { |n| n }
application
expires_in { 2.hours }
scopes { "read" }
end
此外,如果您遇到响应状态:406 而 get '/me'....
表示不支持请求的格式(默认HTML)。您也可以在 HTTP header.
中发送 Accept="application/json" 而不是 '.json'get '/me', params: {}, headers: {
'Authorization': 'Bearer ' + token.token,
'Accept': 'application/json'}
我用这个方法解决了我的问题,也许你可以试试。