Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send CORS headers with Devise if user not authorized (401 response)

I am working on an app, where server and the api-consuming client reside under different domains, so I would like to use CORS. To do so, I have to set corresponding http headers in the server response:

def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = 'http://localhost'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*, X-Requested-With, X-Prototype-Version, X-CSRF-Token, Content-Type'
  headers['Access-Control-Max-Age'] = "1728000"
end

This method is used as a before_filter in ApplicationController.

For some resources the user has to be authenticated and authorized. Requests are done via XHR/Ajax. So if the user is not authenticated Devise will send a 401 response to the client, instead of redirecting to a sign in page. But the filter to set the CORS headers is not used for that response. Thus the 401 response is not sent to the client. I want to catch and use the 401 response in the client.

Currently I am using a workaround by not using the Devise authentication methods, but a custom auth snippet:

def authenticate_cors_user
  if request.xhr? && !user_signed_in?
    error = { :error => "You must be logged in." }
    render params[:format].to_sym => error, :status => 401
  end
end

This is set as a before_filter in ApplicationController, too. This way the filter to set CORS headers gets triggered and everything works fine.

I would prefer to use the default behaviour of Devise, but the CORS headers would have to be set in the 401 response. How to do this? Do I have to configure warden for that?

How could the CORS headers be set for the 401 response generated by Devise instead of creating my own response?

like image 439
Nils Blum-Oeste Avatar asked Jun 24 '12 11:06

Nils Blum-Oeste


1 Answers

I successfully used the rack-cors gem https://github.com/cyu/rack-cors and outlined my experience on my blog.

Punchline: Specify middleware order so cors handler is before warden:

config.middleware.insert_before Warden::Manager, Rack::Cors
like image 87
Mark Nadig Avatar answered Sep 20 '22 15:09

Mark Nadig