Search code examples
ruby-on-railsauthenticationdeviseruby-on-rails-5warden

Devise login with computed / manipulated username param


I'm trying to create a login using devise with a username that I've computed. As an example, let's assume we want to namespace our usernames - and I want to receive a username from the login form, and use namespaced_username to do the actual authentication.

So in my User::SessionsController#create, I might have:

def create
  params[:user][:namespaced_username] = "namespace/#{params[:user][:mobile_number]}"
  super
end

Even though devise is listening for namespaced_username (configured with authentication_keys in either initializers or the model itself), and with a user setup as namespace/username, I still get told Invalid Namespaced username or password is not valid

How can I get devise (the warden strategies, specifically) to read the new param?


Solution

  • It turns out this is a Rails 5 problem. Basically, Warden (which is used by devise) is handed the request object, probably in middleware, and then the controller is handed a copy of the request's params hash.

    The easy way to fix it is, within User::SessionsController#create, we need to add a line:

    def create
      # Here we change params - but this won't be seen by the warden strategy
      params[:user][:namespaced_username] =  = "namespace/#{params[:user][:mobile_number]}"
      # Inject our changes into the copy in request
      request.params[:user].merge!(params[:user])
      # now our changes will be seen by warden - continue with devise:
      super
    end