How to secure database without authentication? - firebase

I am creating an Unity game where I want to have global top 50 score list with usernames. I use Firebase realtime database. There is no need for user to authenticate. I am not that familiar with database security and pretty beginner with this concept. I am using Rest Api from Unity Asset store because it was pretty easy to send and get data from databse.
How can I be sure that every score sent to database is from my app?

Add a dedicated user with password to your database
Somewhere in you app, add those credentials e.g. in a ScriptableObject / in some component
Always use those credentials to authenticate
Note that your app can still be decompiled and thereby cheated.
You can at least make it more difficult by encrypting the data etc.
The only way really around is to have an account and sessioning server to assure a user is locked in with a valid session.

If you don't use Firebase Authentication, you can't restrict who can access your database. Anyone will be able to issues a query, and they can even do it using the Realtime Database REST API. All they have to know is the name of your project.
Even if you do use Firebase Authentication, anyone may still effectively authenticate and access the database outside of your app using other public APIs.

My experience is that you can't stop dedicated "users" from cheating global at high scores. I made a small handfull of trivial games for windows phone with global top 50. Even if your game is unpopular, and you obfuscate your code, and you are on an unpopular platform, and you encrypt your network traffic: somebody is going to jailbreak their phone, decompile your app, and inject their own high score into your game before high scores are sent to the global list. The only way I ever came up with to combat this was to keep track of play sessions -on the server- to make sure their scores were theoretically possible based on how long they were playing.

Disclaimer: I don't know anything about Firebase
From what I can tell, you will need to set up access for Default and Public sections of your configuration to tell the database who can and cannot access your database. Here's their documentation on Get Started with Database Rules.
In general database access, no one should know the details of your connection to a database, so all calls should only ever come from your app.

Related

How to save user data in db, without logging in?

I am working on a simple app that allows users to search for something using an API and save it to view later.
However, I don't want to integrate authentication in the app. I can, but would rather not as a UX decision. Do you know of a way to generate a device token, that is unique to every device and can be used to store which assets a device has saved in the db?
I am thinking of expo push tokens as a possible solution, but that would require users to accept push notifications - so what happens if a user says no?
Sounds like you could just use react-native-uid to generate a unique id for your device and then store it in AsyncStorage and fetch it from there going forward.
For more inspiration, or perhaps just a more canonical way to do this... read up on suggestions surroundings the recently deprecated constant for installationId here:
https://docs.expo.dev/versions/latest/sdk/constants
I haven't used this before but if you're looking for something bullet proof then this is probably your goal of getting the same concept.
Firebase Anonymous Authentication might be ideal to use in this case. This can be used to create a user in Firebase auth without any credentials and can be useful especially when you are using either of Firebase's databases since you can use security rules with user's UIDs.
However, once the user logs out of the account by any means including but not limited to using sign out option in your app, clearing app data or uninstalling the app, the same account with that UID cannot be recovered. I looked up for AsyncStorage and apparently that gets cleared to if the app is deleted.

different types of user management on react-native

I'm new to react native. I am trying to develop an application that uses firebase user authentication. But there is something I can think of. For example, 2 users have registered to my application but I want to show extra information to the first user according to a condition.
How can I separate these two?
Where exactly should I manage this condition?
The question is not super clear as to what issue you are trying to tackle so I apologize if I am inferring incorrectly.
I use MongoDB personally with a Node/Express backend for user data and haven't used Firebase myself but I'm sure you can do the same things with it. I'll be speaking in Mongo terminology but again I'm sure you can do the same with Firebase and at the least this will give a good idea of the thought process.
I have a UserSchema that holds all the user information. When logged in the client app would get this information to be used on the frontend after authentication.
Assuming you are only displaying "extra" information that doesn't need additional privilege you can just pull in the users data stored in firebase and handle the display of this extra info with logic on your frontend client.
If its extra privilege you need to setup firebase to look at the user data that is authenticating and only serve back information if they have the proper privileges.
Also important to note, you should ensure that when you are updating user information from client -> firebase backend you should ensure that you can only update specific user fields via read/write authentication on firebase.
Hope this gives a little better idea on how this process might look. I'll let someone who has used firebase specifically add tech specifics.

Understanding the Firebase and purpose of google cloud functions

Let's say I'm developing app like Instagram: for iOS, Android and Web. I decided to use Google Firebase as it really seems to simplify the work.
The features user needs in the app are:
Authorization/Registration
Uploading photos
Searching for other people, following them and see their photos
I come from traditional "own-backend" development where I do need to setup a server, create database and finally write the API to let the frontend retrieve the data from the server. That's the reason why it's unclear to me how it all works in Firebase.
So the question is how can I create such app:
Should I create my own API with cloud functions? Or it's ok to work with the database directly from the client-side?
If I work with the database directly why do I need cloud functions? Should I use them?
Sorry for such silly questions, but it is really hard to get from scratch.
The main difference between Firebase and the traditional setup you describe is that with Firebase, as far as the app developer is concerned, the client has direct access to the database, without the need for an intermediate custom API layer. Firebase provides SDKs in various languages that you would typically use to fetch the data you need / commit data updates.
You also have admin SDKs that you can use server-side, but these are meant for you to run some custom business logic - such as analytics, caching in an external service, for exemple - not for you to implement a data fetching API layer.
This has 2 important consequences:
You must define security rules to control who is allowed to read/write at what paths in your database. These security rules are defined at the project level, and rely on the authenticated user (using Firebase Authentication). Typically, if you store the user profile at the path users/$userId, you would define a rule saying that this node can be written to only if the authenticated user has an id of $userId.
You must structure your data in a way that makes it easily readable - without the need for complex database operations such as JOINs that are not supported by Firebase (you do have some limited querying options tough).
These 2 points allow you to skip the 2 main roles of traditional APIs: validating access and fetching/formatting the data.
Cloud functions allow you to react to data changes. Let's say everytime a new user is created, you want to send him a Welcome email: you could define a cloud function sending this email everytime a new node is appended to the users path. They allow you to run the code you would typically run server-side when writes happen, so they can have a very broad range of use-cases: side-effects (such as sending an email), caching data in an external service, caching data within Firebase for easier reads, analytics, etc..
You don't really need a server, you can access the database directly from the client, as long as your users are authenticated and you have defined reasonable security rules on Firebase.
In your use case you could, for example, use cloud functions to create a thumbnail when someone uploads a photo (Firebase Cloud Functions has ImageMagick included for that), or to denormalize your data so your application is faster, or to generate logs. So, basically you can use them whenever you need to do some server side processing when something changes on your database or storage. But I find cloud functions hard to develop and debug, and there are alternatives such as creating a Node application that subscribes to real time changes in your data and processes it. The downside is that you need to host it outside Firebase.
My answer is definitely NOT complete or professional, but here are the reasons why I choose Cloud Functions
Performance
You mentioned that you're writing an instagram-like mobile device app, then I assume that people can comment on others' pictures, as well as view those comments. How would you like to download comments from database and display them on users' devices? I mean, there could be hundreds, maybe thousands of comments on 1 post, you'll need to paginate your results. Why not let the server do all the hard work, free up users' devices and wait for the results? This doesn't seem like a lot better, but let's face it, if your app is incredibly successful, you'll have millions of users, millions of comments that you need to deal with, server will do those hard jobs way better than a mobile phone.
Security
If your project is small, then it's true that you won't worry about performance, but what about security? If you do everything on client side, you're basically allowing every device to connect to your database, meaning that every device can read from/write into your database. Once a malicious user have found out your database url, all he has to do is to
firebase.database().ref(...).remove();
With 1 line of code, you'll lose all your data. Okay, if you say, then I'll just come up with some good security rules like the one below:
This means that for each post, only the owner of that post can make any changes to it or read from it, other people are forbidden to do anything. It's good, but not realistic. People are supposed to be able to comment on the post, that's modifying the post, this rule will not apply to the situation. But again, if you let everybody read/write, it's not safe again. Then, why not just make .read and .write false, like this:
It's 100% safe, because nobody can do anything about anything in your database. Then, you write an API to do all the operations to your database. API limits the operations that can be done to your database. And you have experience in writing APIs, I'm sure you can do something to make your API strong in terms of security, for example, if a user wants to delete a post that he created, in your deletePost API, you're supposed to authenticate the user first. This way, 'nobody' can cause any damage to your database.

User authentication when using single database per client?

My company is building an ASP.NET HR application and we have decided to create one database per client. This ensures that clients cannot accidentally view another client's data, while also allowing for easy scalability (among other benefits, already discussed here).
My question is - what is the best way to handle security and data access in such a scenario? My intent is to use a common login/account database that will direct the user to the correct server/database. This common database would also contain the application features that each user/role has access.
I was not planning to put any user information in each individual client database, but others on my team feel that the lack of security on each database is a huge hole (but they cannot articulate how duplicating the common access logic would be useful).
Am I missing something? Should we add an extra layer of security/authentication at the client database level?
Update:
One of the reasons my team felt dual user management was necessary is due to access control. All users have a default role (e.g. Admin, Minimal Access, Power User, etc.), but client admins will be able to refine permissions for users with access to their database. To me it still seems feasible for this to be in a central database, but my team doesn't agree. Thoughts?
We have a SaaS solution that uses the one DB per client model. We have a common "Security" database too. However, we store all user information in the individual client databases.
When the user logs into the system they tell us three pieces of information, username, password and client-id. The client-id is used to lookup their home database in the "security" database, and then the code connects to their home database to check their username/password. This way a client is totally self-contained within their database. Of course you need some piece of information beyond username to determine their home database. Could be our client-id approach, or could be the domain-name requested if you're using the sub-domain per client approach.
The advantage here is that you can move "client" databases around w/out having to keep them synced up with the security database. Plus you don't need to deal w/cross-db joins when you're trying to lookup user information.
Update: In response to your update... One of the advantages to each customer having their own DB is also the ability to restore a customer if they really need it. If you've split the customer's data into two databases how do you restore it? Also, again, you'll need to worry about cross-db data access if the users are defined in a DB other than the home DB.
I've always been of the opinion that security should be enforced at the application level, not the database level. With that said, I see no problem with your intended approach. Managing accounts and roles through a central database makes the application more maintainable in the long run.
You may want to look into using the ASP.NET membership provider for handling the authentication plumbing. That would work with your stated approach and you can still keep all of the authentication data in a separate database. However, I agree with Chris that keeping one DB will utlimately be more maintainable.

Database Authentication for Intranet Applications

I am looking for a best practice for End to End Authentication for internal Web Applications to the Database layer.
The most common scenario I have seen is to use a single SQL account with the permissions set to what is required by the application. This account is used by all application calls. Then when people require access over the database via query tools or such a separate Group is created with the query access and people are given access to that group.
The other scenario I have seen is to use complete Windows Authentication End to End. So the users themselves are added to groups which have all the permissions set so the user is able to update and change outside the parameters of the application. This normally involves securing people down to the appropriate stored procedures so they aren't updating the tables directly.
The first scenario seems relatively easily to maintain but raises concerns if there is a security hole in the application then the whole database is compromised.
The second scenario seems more secure but has the opposite concern of having to much business logic in stored procedures on the database. This seems to limit the use of the some really cool technologies like Nhibernate and LINQ. However in this day and age where people can use data in so many different ways we don't foresee e.g. mash-ups etc is this the best approach.
Dale - That's it exactly. If you want to provide access to the underlying data store to those users then do it via services. And in my experience, it is those experienced computer users coming out of Uni/College that damage things the most. As the saying goes, they know just enough to be dangerous.
If they want to automate part of their job, and they can display they have the requisite knowledge, then go ahead, grant their domain account access to the backend. That way anything they do via their little VBA automation is tied to their account and you know exactly who to go look at when the data gets hosed.
My basic point is that the database is the proverbial holy grail of the application. You want as few fingers in that particular pie as possible.
As a consultant, whenever I hear that someone has allowed normal users into the database, my eyes light up because I know it's going to end up being a big paycheck for me when I get called to fix it.
Personally, I don't want normal end users in the database. For an intranet application (especially one which resides on a Domain) I would provide a single account for application access to the database which only has those rights which are needed for the application to function.
Access to the application would then be controlled via the user's domain account (turn off anonymous access in IIS, etc.).
IF a user needs, and can justify, direct access to the database, then their domain account would be given access to the database, and they can log into the DBMS using the appropriate tools.
I've been responsible for developing several internal web applications over the past year.
Our solution was using Windows Authentication (Active Directory or LDAP).
Our purpose was merely to allow a simple login using an existing company ID/password. We also wanted to make sure that the existing department would still be responsible for verifying and managing access permissions.
While I can't answer the argument concerning Nhibernate or LINQ, unless you have a specific killer feature these things can implement, Active Directory or LDAP are simple enough to implement and maintain that it's worth trying.
I agree with Stephen Wrighton. Domain security is the way to go. If you would like to use mashups and what-not, you can expose parts of the database via a machine-readable RESTful interface. SubSonic has one built in.
Stephen - Keeping normal end users out of the database is nice but I am wondering if in this day and age with so many experienced computer users coming out of University / College if this the right path. If someone wants to automate part of their job which includes a VBA update to a database which I allow them to do via the normal application are we losing gains by restricting their access in this way.
I guess the other path implied here is you could open up the Application via services and then secure those services via groups and still keep the users separated from the database.
Then via delegation you can allow departments to control access to their own accounts via the groups as per Jonathan's post.

Resources