Protecting Firestore without requiring authentication - reactjs

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

Related

Removing data from Cloud Firestore using React

I'm trying to make a simple React app that uses Cloud Firestore for user auth and storing data; something that I could serve using heroku or something like that.
I'm running into trouble with enabling a user to delete their account (and associated data), as Firestore tells me that it's a bad idea to delete collections from the client side. Here's what they say:
Deleting a collection requires coordinating an unbounded number of individual delete requests. If you need to delete entire collections, do so only from a trusted server environment. While it is possible to delete a collection from a mobile/web client, doing so has negative security and performance implications.https://firebase.google.com/docs/firestore/manage-data/delete-data
While I might be able to delete the document connected with the user's account, this suggests that I can't really delete the sub-collections under that document.
So what would be a good way of automatically removing both the user document and user sub-collections? Can I achieve this through my react code? If not, is there a relatively easy way to do it without building a fancy back end?
Well, the documentation never says that this is not possible, just not recommended.
This makes sense if you consider that if you want to delete everything, including documents from subcollection, you would have to create a logic that will do this one by one, which is a very read intensive process and all of this data processing happening in your webapp is not a good practice, it might slow your app down or even block functionality while this process is occuring, etc.
What I would recommend for you is to follow the recommendations of Firestore itself, which is to create a Callable Function that will perform this actions for you, all processing will be done by that function and this will not degrade your app performance, you can find more details in this documentation.

How do I entirely limit access from a frontend framework(react) to specific(admin) pages using REST API(is it possible?)

I'm very new to REST API and frontend JS frameworks world, and I don't really understand how I can limit access for a frontend to specific pages, I don't really think I can, am I? I'll explain:
Usually, if I develop without REST API, I can use backend to determine if a user may access content(on some pages) and block it if needed, so there's no possible way to download(and view) whatever it might/could be presented on that page.
On the other hand, if I make REST API for the same pages, I can only limit the presented data(I will basically block any request to certain protected endpoint), but yet, the user still will be able to download the schema of the page(frontend part), even I will check if user can/can't view the page, still he will be able to download it and see it, because, well... I check it in frontend and all the logic to present the data is also in frontend(that user may see, even though through a code).
Am I getting this right, if not please explain it to me.

User Roles / Permissions on Frontend - React / GraphQL / Apollo Client

Recently started working with React / Apollo Client / Auth0 / Hasura and have some questions on handling frontend permissions. I'm using Auth0 to handle my authorization on whether a user is logged in and have my backend setup to check as well when handling mutations / queries. My question is now how to handle it on the front end.
A user can create a team that will store the info in my "teams" table and also create a record in my "team_staff" table as either a manager or coach. That was all straight forward. What I'm looking to do now is when a user visits, for example: www.mysite.com/team/update/1 to check if the user exists in the "team_staff" table and if not show them an error message or even a redirect. Also looking to hide certain buttons when viewing a team based on whether they are a staff member or not.
Should I handle this at the login and do a query for all the teams that user is a staff member on and store in a session / cookie or have a query / check inside that component each time it's called? Or am I way off and should do it another way?
Hopefully this question makes sense. Thanks!
This question makes sense, I believe many developers would have some similar problems.
TLDR;
Make API request in componentDidMount to get the right permissions (after signed in of course).
For this question, we have many solutions, and which is the best, depends on your infrastructure, your team and so on. Basically you need to call API to check the permission because your permission stored in the backend. Never store permission on the frontend storage like session, cookie, etc.
I can give some approaches.
First, call API right after signed in to get permission information, for example:
Get list of permitted routes, then, whenever user browse to a specific route, check to make sure that route in list of permitted routes.
Get list of permitted team like array of team ids, then in each route, get team id, check if that that team exist in above list.
But I'm sure you will realize they're almost the same, just different the data you get and how to process them. And two solutions totally depends on you.
All API request should be placed in componentDidMount of page component, because you will want to make sure the permission should be applied correctly as soon as the backend has changes.
Happy coding!

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.

In Silverlight programming, how to prevent visitors from caching the downloaded content?

I want to create an online quiz website using Silverlight.
When the registered users are logged in, they can view and answer the quiz once per page.
To proceed to the next question, they must push next button, and the new data downloaded from the server.
The previous questions are not cached. Thereby everytime the question is requested, the question will be reloaded from the server again.
My question is how to do my scenario above in silverlight?
Thank you in advance.
Now that your intent is clear, you want to prevent discovery of the content in your assembly. The answer is you can't really protect your assembly. In order to run it the client needs to fetch it, if it can be fetched then the would be hacker can get it, trying to limit caching isn't really a prevention.
However the solution is to not put senstive stuff in your assembly to start with. Place code server side to do the sensitive stuff and access that code via a service interface such as WCF or Web services or even plain old XML in XML out posting.
You could use IsolatedStorage to store some state related info (and you can even encrypt it before you save if you want - it's your storage, do what you want with it). Another way to store state information is to use cookies, here and here.
The "state" information that i refer to is the state and/or progress of your Silverlight app, i.e. you can track where the user got to in the questions, and avoid requesting questions they have already completed. Both of these types of storage can be deleted by the end user, if they know what they are doing. But you shouldn't let that worry you - if they want to cheat, then let them.
Create the silverlight app to request the questions via a Web Service. As long as you're using a proper web service and not faking it in some way. The browser is not going to cache the webservice response.

Resources