I am using Ruby on Rails 3 and I would like to handle user authentications in a Service-Oriented Architecture (SOA).
At this time I have 3 applications located (for now) on the same server:
pjtname.com
users.pjtname.com
others.pjtname.com
I would like to use memcached (it is a very awesome way to avoid to query the database), but I've heard of problems that can happen when the system goes out of memory, such as the problem for users not being able to log.
However, I am thinking to store in the pjtname.com cache at least the user_id values so that is more hard to go out of memory. The following are steps at what I am thinking to do, but I don't know if it is the best way to accomplish what I aim.
send user credentials from pjtname.com to users.pjtname.com over SSL;
on the users.pjtname.com side use a middleware to intercept and sign in the user;
on sign in success, send back the user session authentication information (example: the user_id string) from users.pjtname.com to pjtname.com over SSL;
on the pjtname.com side look for user_id in cache and if that is expired start again at the step 1.
So, do you advice to use memcached for that purpose?
If so, where I can start?
If no, what approach is recommended?
UPDATE for #Mörre comment
Why do you want to send authentication
info between the sites, can't they
just get the session data from the
(same) database?
It is because I am trying to scale RoR applications on different servers each of them with its own database.
To give architecture advice one would
have to see the WHOLE picture, what
your task is from the customers point
of view, and know their intentions and
constraints.
The "picture" is that I have 3 RoR applications (pjtname.com, users.pjtname.com and others.pjtname.com) for which I need to handle data in order to improve the whole system performance. In this case I need to handle user session on a central place (pjtname.com) in order to access to the other application datas (users.pjtname.com and others.pjtname.com) only if the current user is authenticated, that is, signed in.
Given what you've explained so far, my answer would be no, I would not recommend this. Use a before_filter to authenticate, store the auth in the session.
Now if you had asked if you can use memcached as a session store, I'd say that it is possible. But the overly-complex message-passing scenario you've described would not be helped by using memcached.
Related
I have two models doing login (Devise) in my Rails app - Admin and User, both currently use the default cookie store for session data.
I want to be able to identify an Admin session in AJAX requests coming in from the admin, for authorization of these API calls. I plan to do this by setting an encrypted cookie upon Admin login. When the AJAX API call comes in, I open the cookie, grab some identification from it and look for a matching existing Admin session in the store.
As I understand it, to do this, I must have session information stored in the back-end, either by DB or memcache stores.
I expect to have millions of sessions of Users and just a few sessions of Admin at any given time. For this reason, I don't want to just move all session information to a DB or memory, since this is a heap of unneeded data to store. I only want to store/look at Admin session data.
A solution will be creating some custom model which enumerates Admin user sessions, and is maintained by the app. This is simple enough but requires for instance, a way to clean up sessions when they die without signing out. Essentially this is an attempt to duplicate Rails's session store mechanism, which comes with all the problems of storing and maintaining sessions. Instinct tells me to avoid this solution. Am I correct to avoid it?
If so, then my question is, is there a way to configure multiple session stores in a Rails app, a different store for every logged in Model? In this case, have Admin sessions stored in memory, and User sessions stored in cookie. If not, I'll greatly appreciate any comments and suggestions.
Thanks!
You may be thinking about it wrong.
Session are a low level mechanism that you build your authentication on top of. Its just a cookie containing an identifier (a random hash) which is linked to a session storage (by default cookies). This is a simple mechanism to add persistence to a stateless protocol.
Confusingly we also use the concept "sessions" when talking about authentication - for example logging a user in is often referred to as "creating a session". This is complete poppycock as we are just storing a claim (often a user id) in the session that was created when the user first visits the application.
If so, then my question is, is there a way to configure multiple
session stores in a Rails app, a different store for every logged in
Model?
No. Thats a chicken-vs-egg conundrum. In order to know which session storage to use you would need to access the session storage to know which session storage to use... you get the picture.
While you could create your own session storage mechanism that works differently does this is most likely a complete waste of time. Premature optimization is the root of all evil.
As I understand it, to do this, I must have session information stored
in the back-end, either by DB or memcache stores.
Not quite true. You can perfectly well build an authentication solution with just the cookie storage. In that case Rails just keeps a record on the server of which session identifiers are valid.
The main reason you would need to store additional session information in the database or memcached is if you need to store more data in the session than the 4093 bytes allowed by a cookie. Cookie storage is after all much faster and does the job fine 99% of the time. YAGNI.
You should also recognize that not everything needs to be saved in the session storage. For example the Devise trackable module saves log in / out timestamps on the user table as part of the process of authenticating a user. This is "session information" yet has nothing to do with session storage.
I want to be able to identify an Admin session in AJAX requests coming
in from the admin, for authorization of these API calls.
There are many ways to use different authentication logic for different parts of the application such as Warden strategies. For an API you may want to consider using stateless (and sessionless) authentication such as JWT.
My friends and I are building a Rails app, and we were wondering: Is there any way our database can store user information in a way that we can't read (i.e. we want to honestly say to users, "we can't see your phone number!"), but that our app can still freely read and interact with? We basically need to be blind to the data but still capable of having our app read it.
The only way I can suggest to do this is to encrypt the data on the client side using a password that only the client knows. You will need to find a client-side Javascript encryption library that will encrypt the user's phone number in the browser before sending it to you. Your server will not be able to do anything with the encrypted phone number except to redisplay to the user or to anyone who has the password.
Stanford has a javascript encryption library you may want to explore.
If you want your server to be able to do anything useful with the data (other than storing it), then there is no truly secure way to guarantee that you cannot see the data. Someone in your company, whether it is dev ops, DBA, IT, etc will be able to access the data if they want to. The user will just have to trust that you are keeping their data private.
You can set up encryption and permissions to restrict who has access to the data, but in the end, at least one person other than the client will have access.
It's related to user permissions. You should check the user permissions which are saved on DB and which user retrieves data
If I have a single server with multiple domains, what is the preferred method for implementing a single-sign-on solution on the same domain. I am currently using devise, have a few million cookies in place on separate domains, and am stuck. On top of just implementing SSO, I also need to migrate the various cookies to a central domain. Regarding the various servers, they only have one single page that requires me to show different states depending on whether or not the user is logged in.
I have tried the following:
CORS: pick one domain as the central auth hub. From all other domains make cross domain checks to see if the user is logged in. For migrating cookies, detect if there's a "current_user" object, send it to the client, make a CORS request, sign the user in and kill the token. Works Great! BUT... After building it for 2-3 weeks, it TOTALLY FAILS in IE. Even IE11, I'm noticing the default setting is disabling this behavior.
tried tinkering with the session store at
Rails.application.config.session_store
with no luck.
I am currently experimenting with the following:
JSONP: I have someone right now trying to convert the above to JSONP instead while I try some other options:
Set up a custom OAUTH provider. Like before, it will be the "central domain" if the person is signed in, return to the requested domain with a token from which the users can make requests. https://github.com/songkick/oauth2-provider
Looking at this but it looks outdated? https://github.com/rubycas/rubycas-client. I also get the feeling this could have been a solution if I rolled this out from the get-go, but given how far we are into the project, it's unclear to me how I'd transfer the existing cookies. Also it's unclear if this requires two applications for me to get up and running ( one for client(s), one for auth server)
As I go through each of these possibilities, if anyone has had any experience doing what I'm doing, please do inform me and save me a whole lot of work :)
The best way unless this is a toy app is probably to set up an oauth provider.
We use Doorkeeper with Devise for this and it works great. It will be worth your time to set a little time aside to read through the documentation and watch a talk or two on youtube if you're not already familiar with the strategy but once you understand the core concepts its actually pretty simple to set up with the help of this gem.
There is a quick video run down on http://railscasts.com/episodes/353-oauth-with-doorkeeper
I am making a mobile app for a site with users, so in the app, users need to be able to sign in. To do this, I am creating a remember token to authenticate users on sign in. At first I was thinking about saving each token to the database and destroying it when the user signs out. When the user signs in, they would have the same token until they sign out. Then I saw somethings saying redis was the best way to store the tokens. My question is that if the only time a new token is created is when a user signs in and the only time it is destroyed is when a user signs out, is redis needed or is just saving it to the database ok performance wise
Redis will enable fast access to token data as it keeps the key value pair in memory.
Also, in case you need to expire token after a particular span of time Redis will allow you to set expiration time along with key .Thus you need not perform any explicit computation to determine its expiry time in order to delete it.
A use case of sessions using Redis is Magento.
That commerce framework relies heavily on caching, storing everything in Mysql until v.1.7
From that on, they embedded a model to store sessions in Redis.
I've used Redis with success. phpredis is the best client for php, since it's a c extension.
I would fiddle in heroku's for verifying performance.
(Now I CAN, because of hack support there hehe =)).
My two cents.
I've been working on the development of an Android app in my spare time for several months now. I've done all of my planning for the on-device side (except for server-side interaction), but I've been met with a very steep learning curve for the on-server side implementation. I've researched for about a month with no real leads. Consequently, I'm really at a dead end. The app that I'm working on included these minimal requirements:
Must offer account creation/authentication to the server from the
device
Must maintain some sort of session that allows the user authorization
to make changes that will impact only the on-server user data within the context of the account that they are logged in to.
The ability to log out/be logged out by the server under certain conditions.
A web interface will not be necessary, as this service is only to be consumed by Android devices.
I've decided that a Rails implementation is the most desirable option for me. My experience with Rails and servers in general is very limited. A friend recommended that I read though "Agile Web Development with Rails" in order to get up to speed. I made it through enough of the Depot Application demo in order to understand ORM libraries, the MVC pattern, and scaffolding, but then I got fed up with the way that the book presents the information. Everything is very sequential, and the authors seem to omit a lot of the "how", saying that they'll explain later, and to just not worry about it until that point. That's not the way I learn. I digress.
So far I've used scaffolding in Rails to generate a model, view, and a controller for an Accounts table. I've set up attributes for a username, password, session_key (a randomly generated key that the user should receive and use to connect from their device after login), etc using scaffolding. I am validating the username and session_key to ensure that they're unique, and my alphanumeric key generation is working properly (all of which is done in the model).
Now I'd like to focus on managing sessions in a restful manner. I know that I'll need to implement this by having Android devices pass their user's session key to the server when making HTTP requests and accessing resources etc., but other than that I'm at a loss.
I'm looking for someone to provide me with a good resource (or explanation) outlining how HTTP requests and responses work in general, how JSON information can be received and parsed using a request, and how to otherwise manage restful authorization (assuming that the user has already been assigned their session key). If my approach isn't quite right, please let me know what you would suggest.
Thanks!
For authentication, you might want to check out: http://railscasts.com/episodes/250-authentication-from-scratch You'll basically just be performing the authentication using the session_key. There are other more complicated things you might do, and you could check out authlogic, devise, sorcery, etc. to see how they implement keeping sessions alive. Since you need log outs, and presumably the need to log back in, I would suggest looking into using the session key you describe as the master authentication and then have a perishable key of some sort that gets reset after every request and sent back to the client as a keepalive. Depending on your ultimate needs, that might be enough security and functionality.
For JSON receiving, rails has built-in parsing. Look into respond_to. For sending back JSON, you can use any number of methods. The most basic is to just allow rails to automatically convert the JSON (which happens when respond_with is used, as in the link). You could also build out presenter classes or use something a little more formal like rabl.