RSpec 从 Doorkeeper 请求访问令牌然后总是得到 invalid_grant 错误
RSpec requests an access token from Doorkeeper and then always gets invalid_grant error
当我测试请求访问令牌的过程时,这是授权流程的一部分,从本地主机端的 Doorkeeper gem 到 RSpec 和 [=90= 上的 Ruby ], Devise, Grape and Wine_bouncer, RSpec总是收到Doorkeeper的401响应,其错误描述是Invalid-grant: The provided授权授予无效、过期、撤销、与授权请求中使用的重定向 URI 不匹配,或者已颁发给另一个客户端。
我想知道如何解决这个问题。请帮助我,谢谢。
以下是我的测试环境和代码:
- Ruby 2.3.0
- Rails 4.2.5.1
- 门卫 3.1.0
- 设计 3.5.5
- RSpec-核心 3.4.2,RSpec-支持 3.4.1,RSpec-模拟 3.4.1,RSpec-rails 3.4 .1, RSpec-期望值 3.4.0
- Wine_bouncer 0.5.1
Doorkeeper 配置位于 config/initializers/doorkeeper.rb
Doorkeeper.configure do
orm :active_record
resource_owner_authenticator do
session[:user_return_to] = request.fullpath
current_user || redirect_to(new_user_session_url)
end
authorization_code_expires_in 20.minutes
access_token_expires_in 30.days
enable_application_owner :confirmation => false
default_scopes :public, :description => "Access public data."
optional_scopes :write, :description => "Update your data."
optional_scopes :admin, :description => "Do admin things."
access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
grant_flows %w(authorization_code client_credentials implicit)
skip_authorization do
true
end
end
spec/requests/api/v1/specifiedvegetables_spec.rb
describe SpecifiedVegetables do
describe 'OAuth client requests the grant' do
context 'When a REST client sends a request for getting the grant' do
before(:all) do
post "http://localhost:3000/users/sign_in?user[email]=test%40test123%2Ecom&user[password]=12345678" # Log in the devise
@app = Doorkeeper::Application.new :name => "rspectest-107", :redirect_uri => "https://localhost:3000/api/v1/specified_vegetables/", :scopes => "public"
@app.owner = User.last
@app.save! # Create OAuth client into database.
@authorize_code = String.new # Use later for getting authorize grant code
end
it 'should getting response code 302 for requesting authorization code.' do
query_url = "http://localhost:3000/oauth/authorize"
parameters = { "response_type" => "code", "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/", "scope" => "public"}
headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
get query_url, parameters, headers # Send request for getting authorize grant code
expect(response.status).to eq(302)
authorize_code_param = Rack::Utils.parse_query(URI.parse(response.location).query)
@authorize_code << authorize_code_param['code'] # Get the authorize grant code
end
it 'should get response code 302 for requesting access token.' do
query_url = "http://localhost:3000/oauth/token"
parameters = {"grant_type" => "authorization_code", "code" => @authorize_code, "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/"}
headers = {'Content-Type' => 'application/x-www-form-urlencoded', "Authorization" => "Basic " + Base64.urlsafe_encode64(@app.owner.oauth_applications.last.uid + ":" + @app.owner.oauth_applications.last.secret, :padding => false)}
post query_url, parameters, headers # Send request for getting access token
expect(response).to eq(200) # **Receive the Error response**
end
after(:all) do
@app.destroy # After running all test cases, destroy this OAuth client application.
end
end
end
end
运行 RSpec 命令后 rails 应用程序根目录下的错误响应
- rspec spec/requests/api/v1/specifiedvegetables_spec.rb
expected: 200
got: #, @stream=#, @buf=["{\"error\":\"invalid_grant\",\"error_description\":\"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.\"}"], @closed=false>, @header={"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "Cache-Control"=>"no-store", "Pragma"=>"no-cache", "Content-Type"=>"application/json; charset=utf-8", "WWW-Authenticate"=>"Bearer realm=\"Doorkeeper\", error=\"invalid_grant\", error_description=\"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.\"", "X-Request-Id"=>"97099b43-3456-4396-b9d9-cf744ec38ea6", "X-Runtime"=>"0.006156", "Content-Length"=>"213"}, @status=401, @sending_file=false, @blank=false, @cv=#, @cond=#>, @committed=false, @sending=false, @sent=false, @content_type=#, @charset="utf-8", @cache_control={:extras=>["no-store"]}, @etag=nil>
20160306 PM10:39 UTC+8 更新:
如果我尝试通过 Postman 软件获取访问令牌(从 Chrome 商店获取),我可以按预期获取它。但是试图通过rspec获得它,我无法获得它。
我在RSpec中使用了修改后的ruby类型的代码,这些代码来自Postman生成函数,我仍然无法成功获取访问令牌。我认为这种差异很奇怪。
20160307 PM03:10 更新:
相关文件已放入 at github.com 。我已经通过 Postman 软件获得了访问令牌,但我仍然不明白为什么我可以通过 RSpec 获取访问令牌,尽管我已经尝试了许多其他代码来获得。 RSpec.
仍未解决
我从未使用过 Doorkeeper gem,我使用 Devise Token Auth。我检查了文档并找到了这个。您可以存根 :doorkeeper_token 方法来测试受保护的方法。
let(:token) { double :acceptable? => true }
before do
controller.stub(:doorkeeper_token) { token }
# allow(controller).to receive(:doorkeeper_token) {token} # => RSpec 3
end
https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-protected-controllers
抱歉,我想我在尝试了很多东西后误解了it-statement RSpec 测试用例的用法。
RSpec中it-statement的正确含义:每个it-statement之间相互独立 即使他们处于相同的上下文或 describe-statement。
因此,如果我将请求授权代码和请求访问令牌的两个 it-statement 组合在一起,我将通过 RSpec 的测试。
我需要修复的另一件事是在 HTTP header 处使用正确的授权编码来获取访问令牌。请从 Base64.urlsafe_encode64 更改为 Base64.strict_encode64。
以下是spec/requests/api/v1/specifiedvegetables_spec.rb的正确代码:
require 'rails_helper'
describe SpecifiedVegetables do
describe 'OAuth client requests the grant' do
context 'When a REST client sends a request for getting the grant' do
before(:all) do
post "http://localhost:3000/users/sign_in?user[email]=test%40test123%2Ecom&user[password]=12345678"
expect(response.status).to eq(302)
@app = Doorkeeper::Application.new :name => 'rspectest-107', :redirect_uri => 'https://localhost:3000/api/v1/specified_vegetables/', :scopes => 'public'
@app.owner = User.last
@app.save!
@authorize_code = String.new
end
it 'should getting response code 302 for requesting authorization code and access token' do
query_url = "http://localhost:3000/oauth/authorize"
parameters = { "response_type" => "code", "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/", "scope" => "public"}
headers = {"content-type" => "application/x-www-form-urlencoded"}
get query_url, parameters, headers
expect(response.status).to eq(302)
authorize_code_param = Rack::Utils.parse_query(URI.parse(response.location).query)
@authorize_code << authorize_code_param['code']
# above are acquiring authorize code
# The following are acquiring access token
query_url = "http://localhost:3000/oauth/token"
parameters = { "grant_type" => "authorization_code", "code" => @authorize_code , "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/"}
headers = {"content-type" => "application/x-www-form-urlencoded", "authorization" => "Basic " + Base64.strict_encode64(@app.owner.oauth_applications.last.uid + ":" + @app.owner.oauth_applications.last.secret), "cache-control" => "no-cache"}
post query_url, parameters, headers
expect(response.status).to eq(200) # Here, we get status 200 because the response has access token.
end
after(:all) do
@app.destroy # Destroy the oauth client, but doesn't purge related access token for this rspec request.
end
end
end
end
当我测试请求访问令牌的过程时,这是授权流程的一部分,从本地主机端的 Doorkeeper gem 到 RSpec 和 [=90= 上的 Ruby ], Devise, Grape and Wine_bouncer, RSpec总是收到Doorkeeper的401响应,其错误描述是Invalid-grant: The provided授权授予无效、过期、撤销、与授权请求中使用的重定向 URI 不匹配,或者已颁发给另一个客户端。
我想知道如何解决这个问题。请帮助我,谢谢。
以下是我的测试环境和代码:
- Ruby 2.3.0
- Rails 4.2.5.1
- 门卫 3.1.0
- 设计 3.5.5
- RSpec-核心 3.4.2,RSpec-支持 3.4.1,RSpec-模拟 3.4.1,RSpec-rails 3.4 .1, RSpec-期望值 3.4.0
- Wine_bouncer 0.5.1
Doorkeeper 配置位于 config/initializers/doorkeeper.rb
Doorkeeper.configure do
orm :active_record
resource_owner_authenticator do
session[:user_return_to] = request.fullpath
current_user || redirect_to(new_user_session_url)
end
authorization_code_expires_in 20.minutes
access_token_expires_in 30.days
enable_application_owner :confirmation => false
default_scopes :public, :description => "Access public data."
optional_scopes :write, :description => "Update your data."
optional_scopes :admin, :description => "Do admin things."
access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
grant_flows %w(authorization_code client_credentials implicit)
skip_authorization do
true
end
end
spec/requests/api/v1/specifiedvegetables_spec.rb
describe SpecifiedVegetables do
describe 'OAuth client requests the grant' do
context 'When a REST client sends a request for getting the grant' do
before(:all) do
post "http://localhost:3000/users/sign_in?user[email]=test%40test123%2Ecom&user[password]=12345678" # Log in the devise
@app = Doorkeeper::Application.new :name => "rspectest-107", :redirect_uri => "https://localhost:3000/api/v1/specified_vegetables/", :scopes => "public"
@app.owner = User.last
@app.save! # Create OAuth client into database.
@authorize_code = String.new # Use later for getting authorize grant code
end
it 'should getting response code 302 for requesting authorization code.' do
query_url = "http://localhost:3000/oauth/authorize"
parameters = { "response_type" => "code", "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/", "scope" => "public"}
headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
get query_url, parameters, headers # Send request for getting authorize grant code
expect(response.status).to eq(302)
authorize_code_param = Rack::Utils.parse_query(URI.parse(response.location).query)
@authorize_code << authorize_code_param['code'] # Get the authorize grant code
end
it 'should get response code 302 for requesting access token.' do
query_url = "http://localhost:3000/oauth/token"
parameters = {"grant_type" => "authorization_code", "code" => @authorize_code, "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/"}
headers = {'Content-Type' => 'application/x-www-form-urlencoded', "Authorization" => "Basic " + Base64.urlsafe_encode64(@app.owner.oauth_applications.last.uid + ":" + @app.owner.oauth_applications.last.secret, :padding => false)}
post query_url, parameters, headers # Send request for getting access token
expect(response).to eq(200) # **Receive the Error response**
end
after(:all) do
@app.destroy # After running all test cases, destroy this OAuth client application.
end
end
end
end
运行 RSpec 命令后 rails 应用程序根目录下的错误响应
- rspec spec/requests/api/v1/specifiedvegetables_spec.rb
expected: 200
got: #, @stream=#, @buf=["{\"error\":\"invalid_grant\",\"error_description\":\"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.\"}"], @closed=false>, @header={"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "Cache-Control"=>"no-store", "Pragma"=>"no-cache", "Content-Type"=>"application/json; charset=utf-8", "WWW-Authenticate"=>"Bearer realm=\"Doorkeeper\", error=\"invalid_grant\", error_description=\"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.\"", "X-Request-Id"=>"97099b43-3456-4396-b9d9-cf744ec38ea6", "X-Runtime"=>"0.006156", "Content-Length"=>"213"}, @status=401, @sending_file=false, @blank=false, @cv=#, @cond=#>, @committed=false, @sending=false, @sent=false, @content_type=#, @charset="utf-8", @cache_control={:extras=>["no-store"]}, @etag=nil>
20160306 PM10:39 UTC+8 更新:
如果我尝试通过 Postman 软件获取访问令牌(从 Chrome 商店获取),我可以按预期获取它。但是试图通过rspec获得它,我无法获得它。
我在RSpec中使用了修改后的ruby类型的代码,这些代码来自Postman生成函数,我仍然无法成功获取访问令牌。我认为这种差异很奇怪。
20160307 PM03:10 更新:
相关文件已放入 at github.com 。我已经通过 Postman 软件获得了访问令牌,但我仍然不明白为什么我可以通过 RSpec 获取访问令牌,尽管我已经尝试了许多其他代码来获得。 RSpec.
仍未解决我从未使用过 Doorkeeper gem,我使用 Devise Token Auth。我检查了文档并找到了这个。您可以存根 :doorkeeper_token 方法来测试受保护的方法。
let(:token) { double :acceptable? => true }
before do
controller.stub(:doorkeeper_token) { token }
# allow(controller).to receive(:doorkeeper_token) {token} # => RSpec 3
end
https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-protected-controllers
抱歉,我想我在尝试了很多东西后误解了it-statement RSpec 测试用例的用法。
RSpec中it-statement的正确含义:每个it-statement之间相互独立 即使他们处于相同的上下文或 describe-statement。
因此,如果我将请求授权代码和请求访问令牌的两个 it-statement 组合在一起,我将通过 RSpec 的测试。
我需要修复的另一件事是在 HTTP header 处使用正确的授权编码来获取访问令牌。请从 Base64.urlsafe_encode64 更改为 Base64.strict_encode64。
以下是spec/requests/api/v1/specifiedvegetables_spec.rb的正确代码:
require 'rails_helper'
describe SpecifiedVegetables do
describe 'OAuth client requests the grant' do
context 'When a REST client sends a request for getting the grant' do
before(:all) do
post "http://localhost:3000/users/sign_in?user[email]=test%40test123%2Ecom&user[password]=12345678"
expect(response.status).to eq(302)
@app = Doorkeeper::Application.new :name => 'rspectest-107', :redirect_uri => 'https://localhost:3000/api/v1/specified_vegetables/', :scopes => 'public'
@app.owner = User.last
@app.save!
@authorize_code = String.new
end
it 'should getting response code 302 for requesting authorization code and access token' do
query_url = "http://localhost:3000/oauth/authorize"
parameters = { "response_type" => "code", "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/", "scope" => "public"}
headers = {"content-type" => "application/x-www-form-urlencoded"}
get query_url, parameters, headers
expect(response.status).to eq(302)
authorize_code_param = Rack::Utils.parse_query(URI.parse(response.location).query)
@authorize_code << authorize_code_param['code']
# above are acquiring authorize code
# The following are acquiring access token
query_url = "http://localhost:3000/oauth/token"
parameters = { "grant_type" => "authorization_code", "code" => @authorize_code , "client_id" => @app.owner.oauth_applications.last.uid, "redirect_uri" => "https://localhost:3000/api/v1/specified_vegetables/"}
headers = {"content-type" => "application/x-www-form-urlencoded", "authorization" => "Basic " + Base64.strict_encode64(@app.owner.oauth_applications.last.uid + ":" + @app.owner.oauth_applications.last.secret), "cache-control" => "no-cache"}
post query_url, parameters, headers
expect(response.status).to eq(200) # Here, we get status 200 because the response has access token.
end
after(:all) do
@app.destroy # Destroy the oauth client, but doesn't purge related access token for this rspec request.
end
end
end
end