Rails, Devise, and multiple domains - ruby-on-rails

Let's say I have an application that's going to be accessed from completely different domains that all point at the same server*:
example.com, example.net, foobar.com, ...
I have a Devise based authentication system that's worked fine before. However, the goal is now to add HTTPS to the sign in system. The problem is, as it turns out, there is no way to host more than one HTTPS website on the same IP address**. To resolve this problem, I set up the login pages to always POST to https://secure.example.com. As far as I can tell, this is working fine. Devise seems to have no qualm with it. However, the tricky part is that the user now needs to be redirected to foobar.com, which also needs to understand that the user is logged in. I pass the site to return to in a hidden parameter in the login form, and the redirection works fine. I still have no way to inform foobar.com that the user is now logged in.
I've managed to set it up so that, upon being returned to foobar.com, it copies the user's session cookie for secure.example.com into a new cookie for foobar.com. This part is working fine. However, in the Rails console, the web requests for secure.example.com and foobar.com - with the same cookie sent for each - produce two completely different sessions and therefore, it's no wonder Devise acts like the user was never logged in to foobar.com
Does anyone know why this wouldn't work - why two identical web requests (only the domain of the request URI was different - I tried it in Firebug, too) would produce two completely different sessions in a Rails 3 app with different, yet consistent, session ids? More to the point, does anyone know how to MAKE this work?
* assume, for the purposes of this exercise, that this is unavoidable and the sites cannot be hosted all under different subdomains, and that the number of domains required is too great to get a separate IP address for each.
** unless they're subdomains and you have an *.example.com cert, but that's beside the point.

If you're already using Devise, I suggest you try using token authenticatable. You can generate a token for the user in question, redirect them with the token to sign in, and then quickly expire the token after they have signed in.
You could also try rolling your own OAuth provider with doorkeeper.

Related

Rails: one app with 2 domains - share authentication

My site is at mydomain.com on Heroku with Devise authentication.
I bought a short url me.do that I also point to my same Heroku app.
When a user is signed in on mydomain.com I also need them to be signed in on me.do so when they go to me.do after signing in at mydomain.com they don't have to sign in again.
How can I share authentication sessions using Devise on both mydomain.com and me.do?
There is no easy way to share authentication across domains, since the authentication usually is bound to cookies (sessions) which only bind to one domain and are not accessible across domains.
The only way you can manage to have something like this is to make sure you set cookies on both domains on login. You can do this via a redirect loop:
login request arrives at domain1 (from login form for example)
you set the session cookie for domain1
then make a redirect to domain2 and set a session cookie there
and then redirect the user back to domain1 (proceeding where he originally was going)
to make sure this is not an endless loop you have to add some parameters in the redirects to know how to handle the situation.
BUT if at all possible to avoid it, i would advise you not to implement this. It is really bad practice to have not unique domains. even allowing domains with www and without can lead to quite a bit of confusion for the user and a lot of headaches to the developer - in your case it will be even worse.
The sessions are not as useful as they would normally be. Setting additional cookies or session values does NOT work anymore (unless you do the loop every time again). And until the user actually uses the second domain his session there might even have expired (depending how your authentication framework handles it).
Those are just some of the issues you might run into.

Groovy/GSP redirect around controller

I have a web application that I am trying not to recompile since there is little documentation and the environment is a little sensitive.
With that in mind, all I am trying to do is hijack the authentication mechanism to redirect to one of a couple replacement websites. To that end, there is an authentication service and an authentication controller. The website redirects to /auth/login when the user comes unauthenticated.
In the views folder I have built an alternative /auth/login_new.gsp and from there can authenticate the user and get a redirection back to /auth/redirect.gsp at some frequency but not 100%. That redirect page takes a value from the DB and redirects the user to the correct follow on website. When I run authentication from /auth/login, the site ignores the redirect request to /auth/redirect.gsp.
I had set the show pages for all the different controllers to window.location.href="/auth/redirect.gsp" but I can't get it to go there 100%. I have also reset the layout/domain.gsp file to gut the other functionality of the site and script redirect as well. I was getting errors with duplicate redirect attempts, but now I just go to a dead/gutted homepage...
Any suggestions on how I can dodge the recompile?
Thanks
Leif

OmniAuth dynamic client options site within the strategy

I have a rails app set up as an OAuth2 provider (using Doorkeeper). The app uses a different subdomain per user account (or an entirely different domain through a cname record)
i.e.
user1.myrailsapp.com
user2.myrailsapp.com
www.mycustomdomain.com
On the provider side, everything is working as expected.
I also have a second app that is a client making use of the first app's exposed API. I have a version of the client working but only with a hard coded site url in the OmniAuth strategy.
The question is, how can I dynamically set the strategy url on a per request basis.
For anyone interested, the solution is in the use of dynamic providers: https://github.com/intridea/omniauth/wiki/Dynamic-Providers
Rails.application.config.middleware.use OmniAuth::Builder do
provider :mystrategy, ENV["OAUTH_ID"], ENV["OAUTH_SECRET"],
:setup => lambda{|env|
env['omniauth.strategy'].options[:client_options].site = env['rack.session']['oauth_site']
}
end
One option is don't do it that way.
I have a similar app and ran into the same issue. However after thinking about it for a moment I realised that I didn't want to send them to a strategy provider URL on the user account's subdomain because the request wasn't yet fully authenticated (it hasn't been processed by the rails app yet).
Also for the first time a user logs in the user account subdomain hadn't yet been set up, so it would have been impossible to route there.
So instead, I have the strategy callback URL set to the main website. After the signin request is processed, session set up and everything, then I redirect the client onto their user subdomain. Takes out a whole load of pain.

How do I let a user sign in from a different domain on Authlogic?

[This is slightly different than a previous question about having multiple domains share the same cookie. It seemed like there wasn't an easy way to do that.]
I have a application at application.com. A customer has app.customer.com pointed at my site on Heroku, and I have everything set up so that it renders a specific version of app correctly. The issue is that I want a user at app.customer.com to be able to login. I believe authlogic is now setting the cookie on application.com, so while it verifies the credentials, no session on customer.com is ever created.
Since cookies cannot be shared across domains, you probably need to save an identifier in a database and also pass it through the url so when the client browser hits the new domain, it sends the token for the new domain session to see and match.
It should be a long cryptographically safe token, like a UUID to keep it from being guessed by attackers.
I'm not sure how the authlogic piece fits in though.

Logs out and with every refresh though not using TempDataProvider?

I've got an app built using asp.net mvc and deployed over 2 Amazon EC2 instances. I'm using forms authentication to authenticate users. I simply make a quick look up on the given username and password and if I found a match I set an authentication cookie, like so:
if(_repository.Login(username, password))
FormsAuthentication.SetAuthCookie(username, false);
This works fine as long as the application on one machine, but, once I leveraged Amazon Elastic Load Balancing to deploy the site on two machines, the site behaves in a very weird way. When a user logs in, the site recognizes a logged in user, after a refresh or two, the site no longer see the user as a logged in user. If the user keeps refreshing again for some time, the app sees the user as a logged in user again, and this goes forever.
I'm aware that such a problem might occur if I'm storing SessionState inproc. I'm not using SessionState at all.
What am I missing here guys?
Ps: I've edited the session state to be stored on a state server [Though i'm not using neither sessions nor TempData anywhere on my app] and the same weird behavior is there.
You need to synchronize your <machinekey> between all servers in your farm. Otherwise the forms authentication ticket is only good for the machine which issued it. I doubt this has anything to do with Session/TempData.

Resources