Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise: Have multiple controllers handle user sessions

I am running devise 1.3.4 with rails 3.0.7. I have two ways users may sign in: using the web app, and using a mobile web app (via a JSON API call). The first way is handled perfectly by the default devise sessions controller. The API-call method of authentication needs to be in a controller that extends my Api::BaseController. So, I wrote this second controller like this:

class Api::UserSessionsController < Api::BaseController
  …
  def create
    user = warden.authenticate(:scope => :user)
    if user
      sign_in(:user, user)
    else
      # Do some error handling
    end
  end
end

Attempts to login via this method fail due to the valid_controller? method in Devise::Strategies::Authenticatable. Because I have left the default controller (devise/sessions) as the mapped controller for users, it does not allow authentications from my custom controller.

I would like to roll my custom functionality into my own subclass of Devise::SessionsController, but I need the API sessions controller to extend the API::BaseController, so I can't extend Devise::SessionsController as well. I don't want to place the working, default-behavior web-app authentication methods in the API controller, especially because this would require copying them from the devise controller.

Any suggestions? Is there some config I'm missing that allows multiple controllers to handle sessions? the valid_controller? method does an == comparison, not .include?, so I don't see how that would work.

UPDATE

This is an awful temporary workaround. I don't like it, so I'm not posting it as an answer, but I thought it might offer food-for-thought to all you answerer-types:

In the top of my create method, I could override what Devise expects to be the sessions controller.

Devise.mappings[:user].controllers[:sessions] = params[:controller]

This is working around Devise's intended functionality (requiring a single, specific controller to do session creation) so I don't want to keep it. I wonder if this constraint is a security measure or just a convention -- if it is for security, this is presumably quite bad.

like image 732
andrewmitchell Avatar asked May 26 '11 19:05

andrewmitchell


1 Answers

I can only suggest another workaround (maybe less awful?) In an initializer you can overwrite #valid_controller?, like this:

require 'devise/strategies/authenticatable'
require 'devise/strategies/database_authenticatable'

class Devise::Strategies::DatabaseAuthenticatable
  def valid_controller?
    # your logic here
    true
  end
end

I'd be interested in knowing the reason of this constraint too

like image 175
pic Avatar answered Sep 21 '22 22:09

pic