Best practice to safely persist user data to minify API calls - ruby-on-rails

I have a react app with a rails backend. Users must be logged in to use certain functionality or must be premium users to access premium functionality.
My app makes an API call to the backend on every page load to check if the user is logged in and if so sets the state of the react app to include the user object the API sends as response and sets loggedInStatus: "LOGGED_IN".
The app uses the state and user object to accordingly allow or prohibit functionality.
This means though that on every page load an API call must be made which seems inefficient to me.
An alternative could be to store the data in localStorage and only make API calls and update the user object in localStorage if changes were made to the user. However, storing information like email addresses in localStorage doesn't seem very safe to me.
Is there a way / best practice to securely store and retrieve senstive information without the need for API calls on every page load? Please excuse if this questions seems rather broad, I don't know how to phrase it better.

Related

Rails - Store data that we can't read but that our app can?

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

How to track a user's session without requiring them to login with ruby on rails

I have an application that has an actual map of objects that any visitor can view as long as they have the correct access code. I don't require the user to login because I don't want to make them create an account as it is unnecessary. I want to allow the users to mark the objects on the map with a check and save the edits within the session. So if the user refreshed the page or they close the application and reopen it an hour or so later, I would like to save their marks based off their session id. But I am confused on how to set this up without requiring them to login because I am unsure how the sessions would work.
Any help would be greatly appreciated!
Sessions in Rails work the exact same way regardless if you have a proper authentication system or not.
When a first time visitor visits your application the sessions middleware creates a session identifier. This is a cryptographic hash that is kept by the server and also passed to the user in a cookie.
This lets you identify users across requests.
This session identifier is also linked to a session storage. By default this is ActionDispatch::Session::CookieStore which lets you store session data in a encrypted cookie held by the client. This is where you would normally store a user id. Since its a cookie the amount of storage space is very limited. If you want to store more data in the session you can use a different store such as Memcached, Redis or ActiveRecord.
But what you may want to consider is creating (guest) user records implicitly without the normal sign up procedure. I would just use Warden and have a bare bones user model and a cron tab that cleans out unneeded data periodically.
This gives you a database oriented application model where you can use associations and build it like a standard rails application instead of the untestable mess that results when someone goes bonkers with sessions.
I would implement Cookies (with their permission of course). You can store basic data in it, or even create a sort of ID for them so when they return you can restore their settings

Firefox Extension How to Detect Session

I am trying to figure out how can we detect if we are logged in to a site from Firefox Extensions.
I am planning to invoke a rest api in the target site to detect if the user is loggedin or not. I am not sure what is the right place to make such calls.
Going though documentation, seems like main.js is could be the place where I want to put such method, but then I am not sure how to call form my views this particular method in main.js
There is no generic way to determine that a user is logged in to a site. Every site can, and does, choose their own method of doing so. The most common method is to store a session cookie on the user's machine through the browser. However, the specifics are nearly certain to be different at each site. There is also the question of, in your situation, if there is the possibility that the site permits the user to be logged in for an extended period of time (i.e. not just in a session).
The most probable way to successfully determine how the fact that the user is logged in is recorded on the machine is to look at the differences between what cookies are stored (for the site) prior to the user being logged in, while the user is logged in, and after the user is logged out. There are a large number of extensions dealing with cookies. One of them should probably be able to help with letting you look at the information you need to examine for this investigation.
Once you have that information, you can use a variety of different interfaces in Firefox to access the cookies and see if the user is logged in. Obviously, you will want to listen for changes, and/or listen for a page from the site to be loaded (overlay/bootstrapped, SDK) rather than pooling for changes in the cookies.
MDN refs about the cookie interfaces:
Deal with individual cookies:nsICookie, nsICookie2 nsICookieManager, nsICookieManager2
Deals with the entire cookie string: nsICookieService

How to authenticate Rails application using token from 3rd party API?

I have a Rails application that make several user-specific calls to a third-party API. They interact with a lot of data in the course of filling out a survey, and their progress is stored in HTML5 localStorage until they reach the end of the survey and the data is saved in a local database & localStorage cleared.
The API calls require a token tacked onto the end as an "auth=" parameter. Right now, I have the user log into my app with their username and password to that service, POST those credentials to the "sessions" call of that API, and get a token back in JSON. I store that token in a variable in the controller, and use it to make the successive API calls and present the user's data in my app, etc. etc.
I've learned quite a bit about Rails, but next to nothing about sessions or authentication. Generally speaking, is there anything more I need to do for this to be a secure scenario? I feel like I'm missing something.
Assuming the user's username / password combination for the 3rd party service doesn't hit your servers, seems OK to me.
If your servers see the user's credentials, that's not particularly cool. Instead use OAuth to get 3rd party sign in, and use the token to make requests on behalf of the user. You can usually keep the whole session on the client if you want to avoid saving users to the database.
Storing progress in localstorage sounds fine btw. To preserve values you can have the pages of the form be tabs (so hide the previous form, not a new page) and use:
autocomplete="on"
to signify that the values should be restored to what they were. Try that before writing code to save things to localstorage.

Opening up part of a secured application without compromising the entire application

There's a subset of users which will not have access to the system I'm implementing in the beginning but I need a mechanism for them to capture data for one specific part of the process.
An authorized user creates the original record for a Person with some basic details i.e. First name, last name etc.
I then create a 'DataRequest' record which has a unique guid and the external user is sent an email with a path which is effectively http://sampleapplication/Person/Complete?guid=xxxx
The external user adds additional details like Date of Birth, Eye colour etc, submits and saves to the DB. The DataRequest for that guid is then expired and cannot be accessed again.
The Complete action doesn't have any authorization as these external users do not have user accounts.
My preference is to force these users to use the system but at this stage I'm not sure it's practical.
Is this a bad practice?
Should I be implementing some additional security on this like a one time password / passcode contained in the email? Are there alternative approaches I should consider?
There's nothing wrong with opening up a section of your site to the public. Tons of websites have secured and unsecured sections. However, there's also nothing saying that you have to expose your secure site at all. You can create another site that merely has access to that change those records and make that site alone, public.
As far as securing the information of the user, passcodes by email are the invention of some developer somewhere with limited mental ability or a severe lack of sleep. If the link is only available by email (not discoverable by search engines and not easily guessable), then anyone with the link will also have the passcode, making the passcode to access the link redundant.
You should however log when the email is used to finish the record and then disallow further uses.

Resources