I need to securely store sensitive user data between posts. I've read numerous posts on the pros&cons of both session and application caching, but still don't have a clear winner.
Here's the scenario:
User inputs sensitive information and posts it to the server. He is sent to a read only confirmation screen and asked for an OTP (sent via SMS). Then the data gets posted to the server again. On the second post I need to check that the viewmodel info has not been tampered with and verify the OTP.
So the viewmodel info needs to be cached on the first post, and compared on the second post. This viewmodel contains very sensitive information, so it needs to be stored as securely as possible.
I've though of using session to store an encrypted user data store object, but I'm still not entirely convinced that that would be the best solution?
Advise and guidance on this matter would be greatly appreciated!
If you finally going to store this data in the DB, I assume that you find your DB secure enough for this data. A solution could be storing this data in the DB on the first POST with some additional property that states whether this data is verified (I'll refer to it as IsVerified). Once user verifies the OTP simply set this IsVerified property to true.
Pros of this solution in comparison to session storage are:
You don't have to worry about session expiration. (In case that SMS is delayed for example)
If you are going to have a load-balancer, you won't be able to use sticky session to store your data which means that you will have to use some more advanced session management.
User don't have to submit this sensitive data twice, which means that you don't have to re-validate id.
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
What is the preferred way to store some data on the users computer for long periods of time. I am unsure how long a session lives. As an alternative I could store the data in a cookie, but here I can't find any high level storing API which also takes care of signing my data and make sure it is not tampered with.
How do you typically solve this problem of having a persistent user id between sessions.
Check out these links, they might help you on understanding the cookie handling:
http://m.onkey.org/signed-and-permanent-cookies-in-rails-3
http://www.quarkruby.com/2007/10/21/sessions-and-cookies-in-ruby-on-rails
http://www.tutorialspoint.com/ruby-on-rails/rails-session-cookies.htm
You handle a persistent user with a cookie--but you are quite limited in how much data you can store in a cookie (4K?).
Large sessions should be stored on the database. Some browsers support local storage (HTML5) which may also be an option.
If you want to guarantee it can't be tampered with outside of your application, you should store it on the server-side in a DB. The signed cookies make tampering difficult (or at least detectable), but you're still size-contrained.
ok so, i have this dilemma on how i should save login credentials in mvc at the same time avoid as much hit on the database. i know i can easily use Forms Authentication to save a User instance but is it advisable?
At the moment the way I do it is I store the User Id in a cookie which i then would access everytime an Action gets called that would "require" a login access. Before the action gets accessed the User Id will be used to retrieve a "New" User instance. This will be the same on every Action, I don't store the User in the cookie as I feel like once the cookie is compromised everything about the User shall be available for the hacker (Userid, email, roles, etc)
So if i have a ton of actions that would require a login that will be difficult on my bandwidth. What do you think of the method I'm using? Should I change it to have all the User object be stored in the cookie with a short timeout? Any ideas are greatly appreciated.
thanks!!
It seems like you are trying to address a bandwidth issue. That alone would suggest that you shouldn't store more than you have to (ie: session id) in the cookie.
There are two major problems (among others) for using cookies.
1) They are sent up on every request
2) There is only limited amount of information you can store.
In general, trusting anything the user gives you (that includes encrypted cookies) is bad.
How many concurrent users do you foresee having on your website? Keep in mind that the database will be able to cache certain calls. Furthermore, if you are using a ORM like nhibernate, you will get 2nd level caching there. If all else fails, could you use the in-memory session management?
The biggest problem I have with putting userid's in the cookie is the entropy of that key. Say your userId is an email. All I have to do as an attacker is guess a userid that is valid in your system, and I will "automatically" become that user. The reason why people use sessionID's and then retrieve the user is that in theory sessionID's are harder to guess.
My suggestion would be to use database session management if you are in a load balanced situation. If not, use in-memory. It is fast. Memory is cheap. And unless you are storing 10's of mb of data in session for each user, and you have 10000's of users, you should be fine.
As Ken stated, you should probably be using the standard [authorize] tags available with MVC as opposed to creating your own method.
It sounds like you pretty much implemented form based authentication and something comparable to the [Authorize] attribute.
So if i have a ton of actions that would require a login that will be difficult on my bandwidth
Forms Authentication uses a cookie and is baked into the system. If you don't want to store your user information in SQLServer there are plenty of other options.
It sounds like you are trying to implement something that is already done. In my opinion, let's leave the security stuff to people that know about security. I would suggest working within the framework provided unless you have proof that you solution needs something else!
There is a UserData property on the FormsAuthenticationTicket object that could be used to store additional data other than the Username.
I had a project that had a similar need. I stored the values as a NameValueCollection encoded like a query string:
"email=myemail#some.com&roles=Somebody&roles=Special"
(there's also a handy HttpUtility.ParseQueryString() method that is useful for getting the values back out of the UserData property)
You can use the FormsAuthentication.Encrypt and FormsAuthentication.Decrypt to convert the ticket to and from the Cookie value.
I currently using my own membership implementation on a ASP.MVC project. I've got an Account and an Account can have more than 1 memberships.
I am not sure what is the best approach to follow with Account information being cached. I am currently loading the account information for almost each request from the User property of the controller.
Should I cache the account information? And if where would be the best place, cookies or Session?
I recommend fairly strongly against sessions. They won't scale well and do not fit into web/HTTP type of architectures. See 'Key REST principles' in this REST article if you like the REST stuff.
I would suggest to put the user information in cookies (don't over do it, just really required stuff).
And keep sensitive information in the ASP.NET Forms authentication cookie. See Forms Authentication article, "Step 4: Storing Additional User Data in the Ticket".
Fetch the rest of the data from the database. Avoid premature optimization.
As is often the case with these questions, the answer is "it depends".
Cookies are fine if you are only storing small amounts of string data. There are limitations (4k per cookie, HTTP header limit) and they are sent across the wire with every request and response. You might have to "re-inflate" your account/member info from data stored in the cookie. Users can opt to not accept cookies from your website.
Session is strongly-typed (no re-inflation) and not transmitted with every request/response. There are several options for scaling up session storage if you think your web app will need it. Most small-medium sites use session with no problems.