Standard for storing session key - reactjs

After doing a bit of research on this topic, it seems like session keys have typically been stored as cookies which is nice because they get automatically added to requests. I've been seeing that developers prefer localstorage to cookies due to less restrictions, though. I am building a React frontend, so persisting a reducer in localstorage and managing the session key in that reducer would be very easy. I would need to append this to requests, which seems to be the only downside. Wondering if there is a standard for how this should be done. Thank you in advance!

There are only a few places you can store your keys in the browser:
SessionStorage / LocalStorage
Cookies
Web workers
in memory
Cookies
Cookies are one of the best places to put sensitive keys as long as it has the correct configurations/attributes with them. This includes, httpOnly, secure, SameSite, Domain and making sure they expire in a reasonable time. more reading here for how to set these attributes properly.
Cookies are good to use since they are as secure as HTTPS and cannot be accessed via javascript (if correct atrtibutes are set i.e httpOnly). But note there are still vulnerabilities you have to watch out for such as a CSRF attack, and you would have to include a CSRF token to counter this vulnerability since the cookie gets added to the headers automatically by the browser.
LocalStorage / SessionStorage
LocalStorage and session storage are poor places to keep keys since they are accessible via javascript. You can look here on how Auth0 recommends to store keys, and note they persuade not to store it in localStorage for said reasons.
In Memory
You can store the key in javascript memory (use a closure to encapsulate your key). This has a downside as the key will not persist after refresh/close/new tab etc but is still pretty secure
Web Workers
Web Workers are another place you can store the key. Workers run in a separate global scope than the rest of the application so it keeps them pretty secure, and you can have fine grain control as to what apis to send they key to.
Auth can be tricky and it can be easy to forget to include something important, so make sure you are well read on all attributes and how each piece works. Or go with a pre made options like Auth0 or single sing-on.

Related

Protecting Firestore without requiring authentication

So currently in the project we have a collection of documents that don't require authentication to be read. They are write/update protected, but everyone can read.
What we are trying to prevent is that someone looks at the firebase endpoints and somehow manages to scrape the entire collection in json format (if this is even possible). The data is public, but I want it only to be accessible from our website.
One of the solutions we could think of was SSR (we are already using Next.js), but implementing SSR just for this reason doesn't seem very enticing.
Any suggestions would be appreciated.
EDIT:
Let me rephrase a little bit.
From what you see in the network tab, is it possible to forge/create a request to Firestore and get the entire collection instead of just the 1 document that was intended?
The best solution in your case is SSR. I know, it could sound as not enticing, but well, let's reason on when we should use SSR, then. In your use case, there is an important requirement: security. I think this is already a strong enough reason to justify the usage of SSR.
Also, creating an ad hoc service account for the next.js app, and securing the data with custom rules that allow the read of your data only to that service account, would only improve the overall security level.
Last: reading the data server side should make your site work a little faster, even if it would be difficult to notice, because we are talking about milliseconds. Notice that your page, as it is now, will need to be loaded, before the request to Firebase could be sent. This is adding a small delay. If the data is loaded server side, the delay is not added.
is it possible to forge/create a request to Firestore and get the entire collection instead of just the 1 document that was intended?
If you want to limit what people can request from a collection, you're looking for security rules. The most common model there is some form of ownership-based access control or role-based access control, but both of those require some way of identifying the user. This could be anonymously (so without them entering credentials), but it'd still be a form of auth.
If you don't want to do that, you can still control how much data can be gotten through the API in one go. For example, if you in the security rules allow get but not list, the user can only request a document once they know its ID. Even if you allow list, you can control in rules what queries are allowed.
I think one approach could be writing a Cloud Function that retrieves this public data using the admin SDK. Then, you could set a rule that nobody can read those documents. This means that only your Cloud Function with the admin SDK will have access to those documents.
Finally, you could set up AppCheck for that specific Cloud Function, this way, you ensure that the request is coming from your client app only.
https://firebase.google.com/docs/app-check

Secure JWT token handling in React

I have been searching for a satisfying answer for an hour and I still can't figure out the answer to the question: how to securely store the JWT token on the client side with React?
From what I have read, the localStorage solution in undesirable as it's accessible from third-party scripts. A more secure solution proposed is to use a HttpOnly cookie, but the problem is, it is inaccessible via js, hence it is useless in React.
Therefore, how can I securely store a JWT token on the client side?
In short - you can't securely store token in the browser. If your code has access to the token, then any attacker can also get access to it. That said you can mitigate some risks and decide on a solution which might be "secure enough" for your needs.
E.g. it might be enough for you to keep tokens in the local storage, if losing such a token does not pose a great risk - maybe the data handled by your website is not sensitive.
A viable option is to keep the token in the memory. This way it's a bit more complicated to steal it. Then of course you need to get a new token every time you refresh the page, but you might use SSO cookies to automatically get new tokens in the background.
If you want to go with current security best practices for SPAs, you should investigate the Backend-For-Frontend pattern. You add a lightweight backend component which handles tokens and OAuth flows, and which uses regular cookie-based sessions in communication with your React app. At Curity we created an example implementation of such a component, which you could use as inspiration: https://github.com/curityio/bff-node-express
You can have a look at this great video: https://www.youtube.com/watch?v=lEnbi4KClVw where Philippe de Ryck goes into detail of why it's not possible to securely store tokens in SPAs.

Authentication for single-page apps

Background
I am looking at the OAuth 2.0 Implicit Grant flow where a user is redirected to an authentication service and a JWT token is sent back a Single Page Application(SPA). The token is stored in a cookie or in local storage and, in the examples i have seen, the application will hide/show certain pages based on whether it can find the token in storage.
Issue
The problem is that in all the examples (official from service providers), i was able to manually add any random but properly formed token to the browser's local storage and got access to the 'secured' pages.
It was explained to me that you cannot validate the token in the SPA because that would require exposing the client secret and that you should validate the token on the API server. This means that you can 'hide' the pages but it is really easy to see them if someone wants to. Having said that you are unlikely to cause any real damage because any data retrieval or actions would need to go through the API server and the token should be validated there.
This is not really a vulnerability but the documentation and examples I have seen do not explicitly cover this nuance and i think that it could lead naive programmers (like myself) to think that some pages are completely secure when it is not strictly the case.
Question
It would be really appreciated if, someone who is better informed than i am, confirm that this is indeed how SPA authentication supposed to work?
I am far from an expert, but I have played a bit in this space. My impression is that you are correct, any showing/hiding of functionality based solely on the presence of a token is easily spoofed. Your SPA could, of course, get into verifying an access token.
But that may just make it a little more challenging to spoof. If someone wants to fake the client into thinking it has a valid token, they can likely manipulate the client-side JS to do that. Unfortunately that's the nature of client-side JS. Much of the code can be manipulated in the browser.
Thus far this is speaking to protecting the user from seeing a UI/UX. Most applications are only beneficial when they have data to populate their UI. That's where the API access token strategy is still sound. The server will verify the token and not give the client any data without it.
So while it's unfortunate that JS can be easily spoofed and manipulated to show things the developer would rather not make visible, this isn't typically a deal-breaker. If you have some awesome UI feature that doesn't need data, and you need to secure access to that UI itself, this model may not be the greatest.

Store sensitive, non editable data client side

I have an angularjs app that is on a separate domain than my backend, and the users from my backend all have roles and permissions that allow them access to various areas and elements of my frontend.
Before, I was just storing to a cookie and checking as I needed through the use of angular services and whatnot, cool.
Now the permissions datum have reached the point where they are too big to store in a cookie in the browser. And I'm avoiding Localstorage for fear of user tampering.
The Question:
How do I store the users sensitive data (or anything sensitive, really) that are too big for cookies on the client side in a manner that is safe and doesn't require API calls all the time to get?
I don't want to have to phone home every page change to get this data direct from the server when I need it, because I feel this would be really detrimental to the speed and flow of the site, not to mention the frequency at which this would need to happen would be ridiculous for my app.
Keep in mind that I do proper permission checking on the backend before carrying out any actions, but I'm more concerned about users tampering with their permissions to show certain elements that were removed on the frontside before.
What would be your solution or your advice on this?
If it ends up on the user's computer, regardless of whether it's in a cookie, in local storage, in the URL, in the browser's cache, or anywhere else on the user's computer, assume that the user can see it and mess with it. (You could encrypt it, but if your client-side logic knows how to decrypt it, you're back to step one.)
The best that you can do is exactly what you've described - be sure that the server only carries out authorized actions, and never trusts what the user tells it.

What is the difference between $cookies and localStorage?

what is $cookies vs localSTorage.
$cookies.myFavorite = 'Steve jobs';
localStorage.myFavorite = 'Steve jobs';
$cookies is an Angular module that takes browser cookie functions and wraps them in Angular. Cookies have a smaller storage capacity than localStorage (4k as opposed to 5m) and have the ability to be configured to prompt the visitor for use/acceptance each time you try to use one. This can rapidly detiorate the user experience. Cookies are not recommended for long-term storage of information in a browser for exactly these reasons. Cookies also have a reputation among the technologically illiterate for spreading viruses or somehow otherwise being harmful, neither of which are deserved or completely true.
localStorage (and its companion sessionStorage) are somewhat new to the web with the coming of HTML5 and are very useful. While they can be specifically disabled via settings, most browsers come pre-configured with them turned on and you don't need to worry about it. Unlike cookies, there is no way for the user to be prompted each time the browser wants to use these functions. They are either off or on, and there is no in-between. This makes for a much more seamless experience in your web applications.
localStorage is recommended for storing things in the browser that will persist beyond the current session. To remove things in localStorage you have to explicitly clear them via localStorage.removeItem(itemName).
sessionStorage is recommended for storing things that you do not want to persist beyond the current session. This is because sessionStorage is wiped completely clean when the visitor leaves the domain or closes the browser. This makes it an excellent repository for session-based information such as temporary shopping carts, lists of items to compare, etc.
The caveat here is that both cookies and browser storage can be cleared by the individual user and should not be completely relied upon for storage. Your best bet is always database storage that resides on the server.
$cookies will be overridden and they have a temporary storage.
localStorage have a persistent storage.

Resources