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

redirect_path across subdomains (multi-tenancy) #40

Open
elsurudo opened this issue Jun 6, 2013 · 7 comments
Open

redirect_path across subdomains (multi-tenancy) #40

elsurudo opened this issue Jun 6, 2013 · 7 comments

Comments

@elsurudo
Copy link

elsurudo commented Jun 6, 2013

My Admins log in on one subdomain (admin), but the Users that they can impersonate use a subdomain that depends on their account (multi-tenant setup).

I haven't been able to coax switch_user to be able to redirect to the proper subdomain. In fact, my changes there seem to have no effect at all.

In my initializer, I have:

config.redirect_path = lambda { |request, params| authenticated_root_url(subdomain: current_user.subdomain) }

I realize that current_user probably isn't in scope, but I don't even this this code is being hit...

My logs (on attempting to switch user) look like the following:

[admin] Started GET "/switch_user?scope_identifier=user_5" for 127.0.0.1 at 2013-06-06 16:41:06 +0200
[admin] Processing by SwitchUserController#set_current_user as HTML
[admin]   Parameters: {"scope_identifier"=>"user_5"}
[admin] Completed 401 Unauthorized in 4ms
[admin] 
[admin] 
[admin] Started GET "/users/sign_in" for 127.0.0.1 at 2013-06-06 16:41:06 +0200
[admin] 
ActionController::RoutingError (No route matches [GET] "/users/sign_in"):

It makes sense that the route is not found (it's based on a route constraint), but in general, I'm unsure of how to get this to work.

Any tips?

I'm a bit confused by the "Completed 401 Unauthorized" at GET /switch_user

@lcowell
Copy link
Collaborator

lcowell commented Jun 6, 2013

BTW the 401 is puzzling to me too. switch_user does a 403 if you don't have access, but not a 401. Could the 401 be from something helping you with your multi-tenancy ? What happens if you don't try to redirect across subdomains ?

@elsurudo
Copy link
Author

elsurudo commented Jun 6, 2013

The strange part is that it doesn't seem to matter what I put into the redirect_path lambda... I always get the same result!

That's a good point you bring up about the multi-tenancy. I'm using a gem called devise_basecamper to achieve multi-tenancy by subdomain; will have to look into how it functions a bit more.

@elsurudo
Copy link
Author

elsurudo commented Jun 7, 2013

It turned out to have nothing to do with devise_basecamper...

In my ApplicationController, I have "before_filter :authenticate_user!", so I don't have to repeat it in all of my controllers (basically my whole app is behind authentication).

Since SwitchUserController also inherits from ApplicationController, that before filter causes a 401 unauthorized when we try to call SwitchUserController#set_current_user.

In my controllers where I don't need auth, I would just add "skip_before_filter :authenticate_user!", so something similar to this would need to be done in SwitchUserController. Any idea on how to structure this, without coupling too closely to devise?

I'll also need to make a fancier switch_user_helper that will redirect to the proper subdomain, so I hope you will accept a pull request once I have something working.

@elsurudo
Copy link
Author

elsurudo commented Jun 7, 2013

Of course, just getting rid of that authentication filter will only work in development...

I'll need to think of a way to switch to the User (using his own subdomain "switch_user" URL) while verifying that the Admin that is trying to switch the User is signed in on the "admin" subdomain. Tricky... Any thoughts?

@lcowell
Copy link
Collaborator

lcowell commented Jun 8, 2013

You raise an interesting point for me, which is should SwitchUserController inherit from ApplicationController or ActionController::Base ? For now, I think the way around this would be to create another controller class (AuthController) that sits between you controllers and application controller. It's in that controller that you'd put the authorization filter. eg

class MyController < AuthController
end
class AuthController < ApplicationController
  before_filter :authorize_user!
end
class ApplicationController < ActionController::Base
  # no before filter here
end

Is the idea that in production, someone could log in as an admin and then become another user ? I don't feel clear on the use case.

@elsurudo
Copy link
Author

elsurudo commented Jun 8, 2013

Yeah, that workaround makes sense. I arrived at the same solution myself, in order to not have to modify the gem.

My use case is the following:

  • 2 user classes (Admin and User)
  • Users login through account-specific login pages (each user is tied to an Account object, and each of those has a subdomain associated with it)
  • Admins log in at the "admin" subdomain, and every Admin should be able to impersonate any User. It must work this way in production.

@elsurudo
Copy link
Author

elsurudo commented Jun 8, 2013

I'm starting to think that what I want to do is more complicated that I thought.

Cookies (by default) aren't shared between subdomains, so I can't think of a secure way to simultaneously authenticate the Admin (on the "admin" subdomain), while logging him in as a User (on the user's account's subdomain).

I can allow the cookie to be shared, but I'm not sure if that would be a good move for security.

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants