Centralised Login to multiple rails servers - ruby-on-rails

The situation:
We have a rails application, which runs on 12 different servers (different sets of customers). User credentials are stored in the database of each server. We use Devise for auth.
We have an Android app that, when logging in, you have to select the correct server to connect to.
Requirements:
A centralised login page so users don't need to know which server/url to log in to. This is for the web and android. The user should either:
a) Type their username/email, and be forwarded to the correct server to login.
b) Type their username/email AND password, and be forwarded and logged in to the correct server.
Current Ideas:
Create a NoSQL db table with a list of usernames/emails with the server they need to log in to, the login page can grab the server and forward you on.
Use something like Auth0 to manage user data - however unsure how this would work with our current User credential tables spread across multiple servers.
This is not something I have a huge amount of knowledge on, and looking for criticism of the above ideas/better approaches.

Related

Cross site session creation with Devise

I'm working on a project that uses sessions to manage the currently logged in user with a slight twist, there is no log in form on the actual application. Instead, another site will provide a button that should log in the user and redirect to their profile page.
For example, the customer is viewing their profile on Site A, the 3rd party application. From their profile on Site A they click on a button that should log them in to Site B and redirect to their profile on Site B, the site I'm building.
I'm a unfamiliar with the security concerns for a case like this. My initial thought is that if Site A POSTs via https the user's email address and password, then it should work just as if they were filling the form out on my site, Site B.
What security concerns am I missing here or will this just not work at all?
NOTE: The 3rd party site is basically out of my hands and I'll never convince that team to setup any sort of OAuth protocol, or at the very least its going to take unacceptably long. Plus, OAuth, at least with my understanding is method to accept requests from any number of 3rd parties. No other site except for SiteA will ever attempt to log people in.
This sounds like a typical application for an OAuth provider.
Get an overview and grasp the concept here: http://en.wikipedia.org/wiki/Oauth
There already exists OAuth Providers in Ruby, so you don't have to do everything by yourself: e.g. https://github.com/songkick/oauth2-provider.
But if you really wanna do this without, then I would let the other server generate a hash containing the users id (can be username, email, or database id), a random token, the current timestamp and then sign this using MessageVerifier. Then you can check on your server if the timestamp is within a certain range (some minutes) and if the message verifies (using the same key naturally). If so, then accept the user.
If the other site uses PHP, then you might have to rebuild the generate method in PHP. Find the source in Ruby here.

MVC4 Registration Limit

I've developed a MVC4-project and deployed it (in bèta version). A visitor must login before he can see most of the website. For login, you are required to register. So far so good.
Now there's some weird dude who is trying to register a 100 times, it seems just to annoy me. How can I prevent this? I already have the following:
I have to manually accept registrations (as admin)
I integrated a captcha
So this dude is locked out from my application anyway, but his registration attempts are stored in my database, so it keeps expanding.
My question is: Is there any way to limit registration actions? Like only one time per hour or something like that?
Kind regards
You can store ip in database after registration for one hour. And before registration check if ip exists in database. Or create application level list of IPs instead of DB.

Authenticating against external and then internal databases in rails

A system I'm building requires us to authenticate against our clients database to pull user information from their database. However, they also want us to allow external users to log in and access this system. To authenticate against their database we're using DeviseLDAPAuthenticatable, and were planning on using Devise to add local users.
The plan of action at the high level is:
User puts in log in details
if ldap accepts these
log in
elseif local database excepts these
log in
else
fail
What I'm guessing is that I need to override the authenticate_user! method but it didn't seem obvious what I'd need to include to make sure that the LDAP users could still log in. This question seems like it would be helpful but doesn't explain how to get the session if we're authenticating with device.

Rails, Devise, and multiple domains

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.

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