wardencommunity / warden

General Rack Authentication Framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Warden doesn't preserve locale when thrown

JoeWoodward opened this issue · comments

We have been experiencing an issue where the wrong locale is being used for error messages returned from the Devise FailureApp, I believe it's due to the way that warden throws and catches.

The recommended way of setting the locale for a rails controller action is to use an around_action callback, e.g.

prepend_around_action :with_locale

def with_locale(action)
  I18n.with_locale(current_locale) { action }
end

When warden fails to authenticate it throws and calls a rack endpoint, the failure app... This means that the around_action is exited so the locale is no longer applied.

I don't see any way to tell warden to preserve the locale that was applied when the throw was called. Should warden do this internally?

Or maybe this should be handled by Devise? Perhaps devise should be passing the current locale into the throw call

Actually it's not devise that throws, it's warden in the authenticate! method

I read through the related devise thread. It is important to remember that Warden only deals with Rack. We intentionally avoid any reliance on Rails (ala around_action) because Warden works with all Rack-based frameworks (Rails, Sinatra, Hanami, Grape, etc).

Did you try the changes that were suggested in platformatec/devise#4823 ? It appears from that discussion that changing the middleware ordering will resolve the issue.

This is not related to the middleware stack in my case. I believe other users in that thread also have the same issue and failed to locate the problem. We have resolved the issue by using a custom failure app and manually setting the locale based on the params but this solution is suboptimal as the locale might not always come from the request params.

Another issue we're facing now is that this custom failure app isn't being used while Warden.test_mode! is activated. Looking into a fix for that now.

From reading through the docs I have a feeling there is a solution to the problem that won't require any changes to warden or devise. Will investigate further and report back

I18n::Middleware discussed in heartcombo/devise#4823 serves only to reset the locale after the request completes. It's not about setting the correct locale.

The problem here is specific to the use of I18n.with_locale. I've run a number of tests with the "Invalid email/password" message.

Set I18n.locale in before_action in application_controller.rb:

    before_action do
      I18n.locale = :es
    end

Works.

Set I18n.locale with middleware:

class LocaleMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    I18n.locale = :es
    status, headers, body = @app.call(env)
  end
end
config.middleware.use ::LocaleMiddleware

Works.

Use I18n.locale in around_action in application_controller.rb:

around_action :test_set_locale
  def test_set_locale(&action)
    I18n.with_locale(:es, &action)
  end

Doesn't work for the error message, works for the rest of the app.

Use I18n.locale in middleware:

class LocaleMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    I18n.with_locale(:es) do
      status, headers, body = @app.call(env)
    end
  end
end
config.middleware.use ::LocaleMiddleware

Doesn't work for anything.

(double posting of heartcombo/devise#5247 (comment))

I also had the same issue, and resulted in new rack middleware which handles query param, cookie and HTTP_ACCEPT_LANGUAGE header in this order, then store explicitly requested locale in cookie.
https://github.com/nov/rack-locale_memorable

ps.
Rack::Locale wasn't enough for our use-case since it does handle only HTTP_ACCEPT_LANGUAGE header.

Hey, I finally have a PR up with this change on the Devise side of things: heartcombo/devise#5567, basically carrying over the locale from the request to warden and wrapping the failure app with it. If you happen to still be having this issue and want to give it a shot, let me know if you run into any issues.

Just stumbled upon this issue and the latest PR did not help in my case at first, but after also adding this fix: heartcombo/devise#5602 (comment) - everything works as expected