简体   繁体   中英

How do I stop devise from trying to redirect to /users/sign_in for API requests?

On my react frontend, I have an API request which is being sent to my ruby on rails backend, via the axios library:

        Axios({
            url: "/terms",
            headers: {
                'Authorization': token
            }
        }).then((response) => {
            console.log(response.request)
            setActiveSet(response.data)
            setActiveSetIndex(0)
        }).catch((error) => {
            console.log(error)
        })

When the above request is performed, I see the following chain of responses in my backend logs (ruby on rails):

Started GET "/terms" for 192.168.1.119 at 2021-01-05 13:54:02 -0700
Cannot render console from 192.168.1.119! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by TermsController#index as HTML
Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms | Allocations: 491)


Started GET "/users/sign_in" for 192.168.1.119 at 2021-01-05 13:54:02 -0700
Cannot render console from 192.168.1.119! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by Devise::SessionsController#new as JSON
Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms | Allocations: 907)


Started GET "/terms" for 192.168.1.119 at 2021-01-05 13:54:02 -0700
Cannot render console from 192.168.1.119! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by TermsController#index as HTML
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms | Allocations: 491)


Started GET "/users/sign_in" for 192.168.1.119 at 2021-01-05 13:54:02 -0700
Cannot render console from 192.168.1.119! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by Devise::SessionsController#new as JSON
Completed 200 OK in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms | Allocations: 905)

The .catch block is never called. When I look at the responses, I see 2 successful 200 responses. The 401 responses don't show up on the frontend.

I'm trying to capture the 401 status code, and then display a login form to the user via my react frontend. The backend (devise gem) is trying to redirect me to /users/sign_in, which is not what I want to happen. I just want a 401 so that my react app can display its own login form, but for reasons unknown to me, axios is only showing the response having 200 statuses.

You can modify the responses when authentication fails by changing the failure app :

module MyNamespace
  class FailureApp < Devise::FailureApp
    def respond
      request.format.json? ? api_response : super
    end

    private
    def api_response
      self.status = 401
      self.content_type = 'application/json'
      # optional - send a message in the response body
      # response.body = { error: i18n_message }.to_json
    end
  end
end
# add to config/initializers/devise.rb
config.warden do |manager|
  manager.failure_app = MyNamespace::FailureApp
end

The failure app is just a basic Rack application built onActionController::Metal that gets called when Warden throws (when user authentication fails).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM