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
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
Maybe: Add X-Requested-With: XMLHttpRequest header to outgoing HTTP requests from javascript.
Environment
Current behavior
I add the following to my devise configuration:
When making a request
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 theX-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:
http_authenticatable_on_xhr
probably won't do what you want.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 ofhttp_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
X-Requested-With: XMLHttpRequest
header to outgoing HTTP requests from javascript.