resource_owner_id not being populated - ruby-on-rails

I'm trying to use a Doorkeeper gem to protect my API.
My code looks like this:
initializers/doorkeeper.rb
Doorkeeper.configure do
resource_owner_authenticator do
current_user || warden.authenticate!(:scope => :user)
end
default_scopes :public # if no scope was requested, this will be the default
optional_scopes :admin, :write
enable_application_owner :confirmation => false
end
Here are commands I'm using to connect to my API:
RestClient.post 'http://localhost:3000/oauth/token', {
grant_type: 'client_credentials',
client_id: '26b8e5c92367d703ad35a2fc16b14dc93327a15798068ccba473aa2e3d897883',
client_secret: 'b16079915cdc20b5373f1601e31cece5a84274f772cfd89aec12c90fd110775e'
}
... and ...
RestClient.get 'http://localhost:3000/api/v1/videos', { 'Authorization' => 'Bearer <token_from_previous_request>' }
Which works fine but my problem is, that the returned Token object has an empty resource_owner_id param (this column is not being populated in the DB on token creation). Have you any idea what am i doing wrong? I've been following those tutorials:
https://github.com/applicake/doorkeeper/wiki/Associate-users-to-OAuth-applications-%28ownership%29
https://github.com/applicake/doorkeeper/wiki/Client-Credentials-flow

The client credentials flow "is not associated with a resource owner" (https://github.com/applicake/doorkeeper/wiki/Client-Credentials-flow), so I think it is right that the resource_owner_id is not set.

Related

Problem with create authenticate api using grape in ruby on rails

I want to do authenticate API using grape. For auth I used Devise gem. I try include devise::sessioncontroller into my grape api file but it's caput.
class SignIn < BaseAPI
resource :sign_in do
desc 'Sign in page'
params do
requires :username, type: String
end
post do
User.authenticate(params)
end
end
end
Try the following code. You should be able to authenticate. There are a few extra things you need to set up. Follow this document for more details.
resource :sign_in do
desc "Authenticate user"
params do
requires :login, type: String
requires :password, type: String
end
post :login do
user = User.find_by_email(params[:login].downcase)
if user && user.authenticate(params[:password])
token = TokenGenerator.create(user_id: user.id)
{token: token.access_token}
else
error!('Unauthorized.', 401)
end
end
end

RSpec requests an access token from Doorkeeper and then always gets invalid_grant error

When I testing the procedure of requesting an access token, which is part of authorize flow, from Doorkeeper gem at localhost side through RSpec with Ruby on Rails, Devise, Grape and Wine_bouncer, RSpec always receives a 401 response from Doorkeeper, whose error description says Invalid-grant: 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.
I want to know how to solve this problem. Please help me, thank you.
The followings are my test environments and code:
Ruby 2.3.0
Rails 4.2.5.1
Doorkeeper 3.1.0
Devise 3.5.5
RSpec-core 3.4.2, RSpec-support 3.4.1, RSpec-mocks 3.4.1, RSpec-rails 3.4.1, RSpec-expectations 3.4.0
Wine_bouncer 0.5.1
Doorkeeper configuration at 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
Error response after running RSpec command at root directory of rails app.
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 update:
If I try to get access token through Postman software(get it from Chrome store), I can get it as I expect. But trying to get it through rspec, I can't acquire it.
I have used the modified ruby-type code in RSpec, which are from Postman generate function, I still can't get access token successfully. I think this difference is weird.
20160307 PM03:10 Update:
The related file has been put at github.com . I've gotten an access token through Postman software but I still don't understand why I can acquire access token through RSpec although have been tried many other codes to get. It's still unsolved by RSpec.
I've never used Doorkeeper gem, I use Devise Token Auth. I checked the documentation though and found this. You can stub the :doorkeeper_token method to test protected methods.
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
Sorry, I think I have misunderstood about it-statement usage of RSpec test cases after trying many things.
Right meaning of it-statement in RSpec: Every it-statement is independent between each other even if they're under same context- or describe-statement.
So if I combine two it-statements of requesting authorization code and requesting access token together, I will be at halfway towards passing test with RSpec.
The other thing I need to fix is to use right encoding of Authorization at HTTP header for acquiring access token. Change from Base64.urlsafe_encode64 to Base64.strict_encode64, please.
Following are the right code of 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

testing rails with rspec calling api with authorization

I am trying to write a test using rspec 2.12.2, to test an api written in rails 3.2.6.
However the authorization token is not being passed, have no issue calling this from curl.
get '/API/V1/voucher/XXXXXXXXXXXXXXX/redeem.json', {}, { 'Authorization' => 'Token token=XXXXXXXXXXXXXXX'}
the response back from the request from a overwritten method to return the error in json below.
def request_http_token_authentication(realm = "Application")
self.headers["WWW-Authenticate"] = %(Token realm="#{realm.gsub(/"/, "")}")
self.__send__ :render, :json => { :error => "HTTP Token: Access denied. You did not provide an valid API key." }.to_json, :status => :unauthorized
end
setting the header to this worked.
get '/API/V1/voucher/XXXXXXXXXXXXXXX/redeem.json', {}, { 'HTTP_AUTHORIZATION' => 'Token token=XXXXXXXXXXXXXXX'}

request.env['omniauth.auth'] is always nil when using seperate admin login using omniauth-identity gem

I want to use seperate admin login for my application using idenity provider.
I have written this in config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :identity, :model => Credential, :on_failed_registration =>SessionsController.action(:register)
provider :identity, :model => Credential, :name => 'admin', :on_failed_registration => SessionsController.action(:login_admin)
provider :google_oauth2, '000000000.apps.googleusercontent.com', '00000000000'
end
In config/routes.rb
match '/auth/admin/callback', :to => 'sessions#authenticate_admin'
In app/controllers/sessions_controller.rb
def authenticate_admin
auth_hash = request.env['omniauth.auth']
session[:admin_user] = auth_hash['user_info']['email']
if admin?
redirect_to '/'
else
render :text => '401 Unauthorized', :status => 401
end
end
But when i try to access request.env['omniauth.auth'], it always gets nil. While it is accessible when using default callback for normal users at sessison#create action. I just want to know if there is anything that has been missed in this code. I am following this blog http://www.intridea.com/blog/2011/1/31/easy-rails-admin-login-with-google-apps-and-omniauth.

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.
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
...
I know that this question has already been answered but here's my take on it. Something which worked for me:
request.headers['Authorization'] = token
instead of:
request.env['Authorization'] = token
This is another way to do it if you are doing a post.
#authentication_params = { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(Temp::Application.config.api_key) }
expect { post "/api/interactions", #interaction_params, #authentication_params }.to change(Interaction, :count).by(1)
Note interaction_params is just a json object I am passing in.
I don't think you should depend on the header if you are not testing the header itself, you should stub the method that checks if the HTTP_AUTORIZATION is present and make it return true for all specs except the spec that tests that particular header
something like...
on the controller
Controller...
before_filter :require_http_autorization_token
methods....
protected
def require_http_autorization_token
something
end
on the spec
before(:each) do
controller.stub!(:require_http_autorization_token => true)
end
describe 'GET user' do
it 'returns something' do
#call the action without the auth token
end
it 'requires an http_autorization_token' do
controller.unstub(:require_http_autorization_token)
#test that the actions require that token
end
end
that way one can forget the token and test what you really want to test

Resources