Doorkeeper gives 401 Unauthorized - ruby-on-rails

i am using doorkeeper gem
my ApplicationController look like this:
private
def current_resource_owner
Person.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
my DemosController look like this:
doorkeeper_for :index
respond_to :json
def index
respond_with current_resource_owner
end
response comes like this:
Started GET "/?code=f88d2e95b1b286645d31772c395e0e36708a5i0p970836af640f631bb4f043b5" for 127.0.0.1 at 2014-01-28 11:10:56 +0530
Processing by DemosController#index as HTML
Parameters: {"code"=>"f88d2e95b1b286645d31135c395e0e36708a5b5b970836af640f631bb4f043b5"}
Filter chain halted as #<Proc:0xb608b90#/home/xyz/.rvm/gems/ruby-1.9.3-p484#verticalserver/gems/doorkeeper-1.0.0/lib/doorkeeper/helpers/filter.rb:8> rendered or redirected
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)

This is actually an issue on Doorkeeper. To have a custom JSON response for 401 Unauthorized errors instead of a blank page, in ApplicationController I added:
def doorkeeper_unauthorized_render_options
{json: '{"status": "failure", "message":"401 Unauthorized"}'}
end

I'm not 100% sure if I understand your question correctly. Your code looks fine, but the request seems to be wrong.
With Doorkeeper you need an Access Token and not the Code parameter to access the resource (DemosController#index). So first of all you have to get the Access Token from the Authorization Code. Therefore make a request
GET "/oauth/token?code=...&grant_type=authorization_code&redirect_uri=...&client_id=...&client_secret=..."
Make sure that the redirect_uri matches with the one registered with your client application and add the correct client_id and client_secret to the request. Also use always a fresh code parameter. Per default it is only valid for 10 minutes after generation. Notice, in case of customized Doorkeeper routes the url (/oauth/token) might be different.
If you done the request correctly, the response will contain a valid access token.
Then make a GET request to "/index.json?access_token=..." instead of "/?code=...". '.json' tells Rails your client can handle JSON. Otherwise you will get a 406 Response, which means that the requested format (by default HTML) is not supported. Instead of '.json' you can also send Accept="application/json" in the HTTP header.
The 401 Unauthorized response, what you're currently receiving, means that the authentication information (in your case a valid Access Token) is wrong or missing at all.
Hope that helps.

Your respond_to also needs to respond to html because you are requesting "DemosController#index as HTML"
respond_to :html, :json

May not be the answer for you, but it may be the answer for you.
We downgraded our version of doorkeeper and it solved the problem. march2019
https://github.com/doorkeeper-gem/doorkeeper/issues/732

Related

HTTP Token: Access denied

i m getting message "**HTTP Token: Access denied**" when access via browser http://localhost:3000/api/v1/tasks.json?auth_token=szVkqLnUbdzbekV8B-n_
but when i access from terminal that's working on success curl http://localhost:3000/api/v1/moments.json -H 'Authorization: Token token="szVkqLnUbdzbekV8B-n_"'
here code
class Api::V1::TaskController < ApplicationController
before_action :autentifikasi
def index
#tasks = current_user.tasks
end
private
def autentifikasi
authenticate_or_request_with_http_token('Premium') do |token, options|
#current_user = User.find_by(authentication_token: token)
end
end
end
end
anybody help me please !! what's wrong with my code ?
There is nothing wrong with you code - the error is in your testing methodology.
The cURL example properly sends a Authorization: Token header and sends the token along as well.
Requesting http://localhost:3000/api/v1/tasks.json?auth_token=szVkqLnUbdzbekV8B-n_ in a browser would simply set params['auth_token'] as it is a query parameter. Which will of course cause the authentication to fail.
Rails and most sane frameworks do not treat HTTP headers and query parameters as equivalent. That would leave your app looking like swiss cheese.
If you want to test token based auth via a browser you should use a plugin such as Postman which allows you to setup the request headers. Better yet is to write an actual automated integration test.
A Guide to Testing Rails Applications
RSpec Rails: Request spec
Postman
It is because authenticate_or_request_with_http_token expects an Authorization: Token from in a request header.
You are setting the header in the cURL command while in browser you are passing it as a query parameter.
So there is no token in the Request Header so your method is unable to find the token when accessed via a browser.

Using response_with in Rails, how can I prevent execution of create action on not accepted MIME types?

I'm building a RESTful API using Rails 3.2.21. The API should only response to xml or json for now. I have a simple resource called Users with a create action, that creates a new user on a POST Request.
Here is the Code for doing that:
respond_to :json, :xml
def create
#user = User.new(params[:user])
#user.save
respond_with(#user)
end
Everything goes fine so far, but then I tried to check the error cases. So if I do a POST request to /users.html, the answer is '406 Not Acceptable'. What is correct. But then I saw in the database, that the user was created anyway. So the create action is executed although the requested accept format (html) is not supported and a 406 error is responded.
I don't know if this is intended. Until now I really liked response_with from Rails, because it does lots of stuff for me, but this behaviour seems to be odd. From the perspective of a client you try to create a new user, receive 406 and you obviously assume that the request failed, so the user is not created, right?
Since I've defined the accepted MIME types in the class method respond_to, it should be possible for Rails, to prevent execution of the entire action. Sure, respond_to is only related to the http response, but then for the client it is still unknown which part of the POST request succeeded and which failed.
Are there any setting or additional functions in Rails what I've overseen or is this just 'not thought to the end' in case of POST requests using respond_with or is this behaviour even intended to react like that? Of course I can add some custom before_filters for checking the MIME types, but then I can also remove respond_with and handle everything on my own.
I'm looking for a nice and clean solution for that problem using respond_with.

Capture response sent to webhook rails?

I'm working with my first webhook in my rails application. My HookController is receiving the following response:
Started POST "/hooks/callback" for 127.0.0.1 at 2014-11-18 14:10:13 -0500
Processing by HooksController#callback as HTML
Parameters: {"Status"=>"<?xml version=\"1.0\"?>\n<BackgroundReports userId=\"username\" ...
Completed 401 Unauthorized in 1ms
I'm trying parse the XML that is returned in the parameters and I'm getting stuck.
I have tried starting with the following in my controller raising :
webHook = JSON.parse(params[:status])
raise webHook.inspect
But it appears as if its not capturing the params.
How do I capture the params and parse the XML in my controller?
I was able to troubleshoot the problem myself.
I am using Devise for my User model. That was driving the 401 Unauthorized error. As a result I was not able to to pull and parse the params.
I found the answer in a similar question -> Webhook returning 401 in Rails on Stakoverflow. Adding the following allowed Devise to authenticate the response. I could parse the params from there:
skip_before_filter :verify_authenticity_token, :authenticate_user!

"WARNING: Can't verify CSRF token authenticity" error - CORS with Devise and :token_authenticatable

I have a single page app that authenticates to another domain using CORS. All the requests are JSON requests.
My app can authenticates OK and can make GET requests OK. Authentication is using token_authenticatable. I.e. all requests append '?auth_token=whatever'
So, my actual problem is that when I try to do a PUT request I get a WARNING: Can't verify CSRF token authenticity message in the rails log as well as a CanCan::AccessDenied (You are not authorized to access this page.) exception.
Simply adding skip_before_filter :verify_authenticity_token to the rails controller fixes the issue.
Therefore I can only conclude that my ajax requests are sending an invalid or empty csrf_token.
I don't really understand how that can be, since I believe I am correctly sending the X-CSRF-Token header correctly with each ajax request.
Basically, my app authenticates and Devise sends back an auth_token and a csrf_token:
render :status => 200, :json => {
:auth_token => #user.authentication_token,
:csrf_token => form_authenticity_token
}
I then store those tokens in my ajax app, and using ajaxSend in jQuery, set it up so jQuery passes those tokens with each request:
initialize: ->
#bindTo $(document), 'ajaxSend', #appendTokensToRequest
appendTokensToRequest: (event, jqXHR, options) ->
if not #authToken? then return
if #csrfToken?
jqXHR.setRequestHeader 'X-CSRF-Token', #csrfToken
if options.type is 'POST'
options.data = options.data + (if options.data.match(/\=/) then '&' else '') +
$.param auth_token:#authToken
else
options.url = options.url + (if options.url.match(/\?/) then '&' else '?') +
$.param auth_token:#authToken
I can then see in the chrome network tab, that for each GET request the auth_token param is being sent, as well as the X-CSRF-Token header.
On PUT requests however it doesn't seem to be working though.
My theory is that CORS is stuffing things up. If you make a CORS request, your browser actually makes an additional OPTIONS request first just to check that you do have permission to access this resource.
I suspect that it is the OPTIONS request which is not passing the X-CSRF-Token header, thus rails immediately invalidates the csrf_token on the rails end. Then when jQuery makes the actual PUT request the csrf_token it passes is no longer valid.
Could this be the problem?
What can I do to prove that? Chrome doesn't seem to show me the OPTIONS requests in the network tab to help me debug the issue.
It's not a major issue, because I can just turn the CSRF stuff off. But I'd like to know why it's not working.
I think you'll need to handle the OPTIONS request, which should respond with the various headers that will allow the CORS request, IIRC they are the access-control-allow-method, access-control-allow-origin and access-control-allow-headers. Because the OPTIONS request is failing, the PUT request probably isn't occurring.
I just ran into the same issue. The problem is that the _session_id cookie cannot be sent in CORS. As a result, when Rails tries to verify the token, the session[:_csrf_token] is null and Rails generates a new one before comparison.
To solve the issue, you need to enable cookie sending in CORS. Here is the Mozilla Developer Network reference. Work is needed on both the server and client side to make it work.
Client
- Refer to your client technologies document.
Server
- Set the header Access-Control-Allow-Credentials to true (string) in the response to the preflight (HTTP OPTIONS) call.
In Rails every form submission need CSRF token authenticity.
It use to submit form securely.
The CSRF token(each time) will create newly in rails when we open our Application.
If the CSRF token not passing inside our controller this WARNING will show.
We need to pass this token in all form submissions.

Rails: json response from secure action

Originally I had quite usual ajax form with json response:
def create
# created logic omitted as most likely irrelevant
render :json => {:success => true} #over simplified JSON for debug purposes
end
So far so good, works as expected. I've added security on the create action via ssl_requirement gem:
class RegistrationsController < Devise::RegistrationsController
ssl_required :create
# rest of the code omitted, 'create' action as above
end
All of a sudden I get the following in my form response (observing in HttpFox):
Error loading content (NS_ERROR_DOCUMENT_NOT_CACHED)
The create action runs as expected (enforces HTTPS, creates an object but... fails in the browser. To be specific, fails in Firefox (works on chrome). Any clues and ideas will be greatly appreciated.
Regards,
I'm not certain, but I believe your problem has to do with cross-site AJAX requests.
The fact that you are using a different protocol is making firefox believe you are making a cross-site request. Chrome, I believe, is less strict with this restriction when on local. Try visiting the site itself over https and see if the AJAX request goes through.

Resources