Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http_authenticatable_on_xhr and request.xhr? check are always false these days #5593

Open
dleavitt opened this issue May 3, 2023 · 0 comments

Comments

@dleavitt
Copy link

dleavitt commented May 3, 2023

Environment

  • Ruby 3.1.1
  • Rails 7.0.4
  • Devise 4.8.1

Current behavior

I add the following to my devise configuration:

config.http_authenticatable = true
config.http_authenticatable_on_xhr = false

When making a request

  • via Javascript (specifically fetch)
  • that triggers an auth failure (401)

The response contains the "WWW-Authenticate" header, which triggers a basic auth prompt in my browser.

Expected behavior

Because I have http_authenticatable_on_xhr set to false, I should not receive any prompt, just a 401 error that my javascript can then handle.

Problem / Solution

Devise uses Rack::Request#xhr? to decide whether a request is xhr / "ajax" or not. Rack in turn uses the value of the X-Requested-With HTTP header, which is not set by fetch or either of the two request libraries I looked at (axios, apollo client.)

I don't think it's a very useful way, as of 2023, to detect whether a request was initiated from javascript.

However, this detection seems non-trivial and maybe not something devise wants to be in the business of, so the shape of a good solution might be:

  • Update the documentation to indicate that http_authenticatable_on_xhr probably won't do what you want.
  • Add a new config setting http_auth_header (or something) that defaults to true, and, if set to false, always disables the "WWW-Authenticate" header. This probably is what most users want out of http_authenticatable_on_xhr, as it will disable the prompt for "ajax" requests (where you don't want it) and API request (where you don't need it.)

Happy to look into this a bit more and submit a PR!

Workarounds

  1. Use a custom failure app:
# lib/my_failure_app.rb
class MyFailureApp < Devise::FailureApp
  # Force devise not to send the WWW-Authenticate header (which pops up a
  # basic auth prompt) on fetch requests (or ever.)
  def http_auth_header?
    false
  end
end

# config/initializers/devise.rb
require "devise/my_failure_app"
Devise.setup do |config|
  # ...
  config.warden do |manager|
    manager.failure_app = MyFailureApp
  end
  # ...
end
  1. Maybe: Add X-Requested-With: XMLHttpRequest header to outgoing HTTP requests from javascript.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant