Firestore security for game where users do not have account - firebase

I am confused on the insistence in the documentation to have users sign on to give authentication. With a card game app, I want users to get on easily (without a need to sign on), find a game to play in, and play the game. As cards are played, each turn is recorded in Firestore, and all users notified to read the changed parameters. So all users can read, write and update.
Even if I did make users sign on, anyone could create an account, and I would be no further ahead except I have turned away some game participants.
I know I can set rules so that all data is a small size. I maybe check to ensure no data is stored after a certain time without being used, and I could delete the collection for that game. Is is it this sort of procedures I use to guard the database from growing too big, or a 'bad' user working out where the data is, and overwriting data for some games.

If you want a low-friction way to get users signed in, use anonymous authentication. It will give the user an account with a UID without requiring any prompts. You can then use security rules to protect per-user information, since anonymous accounts have a UID just like normal accounts. You can then decide to let the user upgrade that account when they want a more permanent identity in your game (since anonymous accounts become inaccessible if the user clears their device local storage).

Related

Rate limiting for creating new custom tokens for a user?

My team is using Firebase Auth in our project. We're using custom claims to properly authenticate whether or not a user has access to a specific piece of information. We're storing each piece of information and deciding access for the user based off whether or not the user has access to a specific location. Each piece of data is somehow associated with a location, and we are storing the location id in the custom claims for the ID Token.
The problem is that a user potentially has access to thousands of locations. Instead of storing thousands of locations in the custom claims, we think it's better to generate a new custom token and exchange it for a fresh id token every time the user switches locations. That means that it's potentially reasonable for a user to generate a new custom token every few seconds as they switch through their locations if they are doing it quickly enough.
The Firebase Auth documentation doesn't indicate anything in regards to any rate limiting in this regard.
Are we going to run into any issues / rate limiting if a user switches through their locations very quickly? This would be unusual, but I just want to make sure that the worst case will still work.
The control of Firebase Authentication custom claims is an Admin SDK operation and as such is not subject to rate-limiting. Firebase Authentication as a whole is designed to handle millions of concurrent users and is subject to various rate limits. Updating a user's custom claims would only contribute to the overall limits of 1000ops/sec and 10 million ops/day (at time of writing).
However, custom claims should be used for access control related data that will infrequently change such as the name of a role or a building ID. This is because the propagation of changed custom claims can take up to an hour and requires that the client code manually refresh their tokens after any changes to see an immediate effect. Custom claims have no mechanism to notify clients that they have been updated.
I'd reconsider your approach and store the list of locations a particular user has access to in the Realtime Database or Cloud Firestore rather than the ID token itself. You can then use this information to secure their access using appropriate Security Rules for those databases based on their user ID. By configuring a listener to that portion of the database, your client code can be instantly notified when a user gains or loses access to a new location. Additionally, you can poll information from multiple locations at once so you can show information in a notification feed or dashboard - something that can't be done with the claims strategy.

Unity Firebase auto create anonymous account

Seeking some thoughts here. When someone launches my mobile game for the first time, I would prefer they get into the gameplay first before having to worry about "signing up".
I think this provides for a better user experience as you can instantly jump into gameplay. Firebase supports anonymous accounts and saving progress against anonymous accounts, which can later be converted to an actual account (e.g linking their google or facebook accounts to their anonymous account) while retaining their game progress.
Does anyone have any thoughts on this approach or is it better to force a user to decide at app-launch to make a choice between creating an anonymous account or registering using google / facebook / email / etc?
Cheers
Kevin
This is actually a very similar use case to what it often pitched to web developers using Firebase:
For a shopping app, you'll often let a developer go through the shopping flow and finish checkout. When checkout is complete, you then "promote" their account to a full account so you don't bounce a customer out during the critical flow.
For a game, not only do I love this anonymous account flow (play now, then "upgrade" for any social features you need), but I think you can get a really cool natural flow going on. For example, if you were making tic tac toe, you could use a dynamic link to invite your friends to play against you. This link will usually persist across app installation (iOS and Android, although it's a little flakier on iOS) so the player you invite can jump right into the game you're playing using Anonymous Auth to seamlessly create an account.
There are two considerations you need to make though:
You're still storing user data if you pair Realtime Database with an anonymous account. I am not a lawyer, but if your region has strict privacy regulation you will want to talk to one.
The merging an anonymous account into a "full" account process does have some non-trivial edge cases. What do you do if the player already has a full account (obviously, you have to merge the data. But you'll have to do it by hand as there's no game-agnostic way for Firebase to do it for you)? What do you do if a different user claims the same email address when you promote your account (you'll need to throw one out, and there are rules for resolving which has the stronger claim to the name)?
2 is a little complicated also by the current architecture of the Firebase auth SDK as well. All of the C# objects are pointers to C++ objects under the hood. The "current user" was bound in a way that it references a global singleton on the C++ side representing user data. This has the unfortunate side effect that you can't cache a user data on the C# side in the case of a user entering their credentials incorrectly when "upgrading" an account (usually manifesting itself in having to re-enter a username/password and maybe losing cached data). This bug is actively being tracked (I believe it's a side-effect of this one), but in the near term it just means that you probably want a good way to either re-upload local data (assuming you'll lose access to the DB node once you drop the anonymous account) or you'll want to avoid persisting any user-specific data before migrating a player to a "full" account (probably a consideration I'd have with current privacy regulations anyway).

How to sync IndexedDB with Firestore?

I am building a job portal for the web using React, Redux and Firebase/Firestore. I've completed all the features I needed except one.
I want unregistered-users/job-seekers to be able to:
Bookmark job posts.
Keep the record of applied jobs.
Keep the record of search queries.
I am thinking about using IndexedDB for this feature. Particularly Dexie.js to make things easier. However, this data will be persisted in user's browser and user will have no access to it in another browser or device. Therefore, I want to give users an option to be able to save all the data to Firestore if user sign into the website and I need this to be automatic. So, as soon as user signs in, I will save it to the database.
I thought about using Anonymous Authentication instead of IndexedDB/Firestore, so all the data will be saved into the database and as soon as user signs in using credentials, the user can claim the ownership of the data. However, this is an extra step to use these features I listed above and not everyone is happy with authenticating an app even though nothing is required from the user. Besides, there will be so many ghost accounts.
So, as I mentioned in the title; I want to save everything to IndexedDB (I will take care of this), but how am I going to synchronize all the data in IndexedDB to Firestore as soon as user signs in?
I imagined the basic process will be like this:
User clicks "Bookmark Job Post"
App checks if users is authenticated or not.
If authenticated, save the bookmark to the Firestore.
If not authenticated, save the bookmark to the IndexedDB.
If User decided to sign in or sign up, check IndexedDB and synchronize it with Firestore and clear IndexedDB.
How can I achieve the 5th step technically? Is there any built in system in Firebase? Also, please feel free to share your idea if you can think of another way implementing this feature. Should I be using firebase.auth().onAuthStateChanged() for the 5th step?
And lastly, how should I structure the Firestore to save bookmarked jobs, applied jobs and search history?
Should I create a bookmarkedJobs collection and have documents of jobPosts duplicated for each user, who bookmarked the job post? And every time a job post is updated by an employer, I will have a cloud function going through bookmarkedJobs collection, updating every instance of it?
Thank you
This may be of interest to you
https://dexie.org/docs/Syncable/Dexie.Syncable.js
Been looking into making my website fully static/pwa, and just using indexeddb, and some webservice for data handling/storage ..this seems like a interesting route to explore.

Firestore security rules for digital transactions between users

Our app allows authenticated users to send and receive digital coins from each other in the app. Each user has a coins field which stores the current coin balance of a user. To transfer coins, we use firestore transactions at the sender's end to subtract the value of coins from the sender and then add the value to the receiver's balance. Hence, while the sender is logged in, they have to make writes to the receiver's document. This approach is insecure since we only check if the sender is logged in. This enables any authenticated user to have write access to another user's document.
Is there a much better/secure approach to implement such kind of transactions between users and is it possible to handle the problem only using firestore security rules in this situation?
In this scenario, you wouldn't want to give users write access to each other user's documents, or even their own "wallets". Doing this type of transaction all in the client side (e.g. using Firestore iOS/Android/Web SDK) will likely cause security issues down in the road. Of course, not many users will be aware of it, but tech savvy users who finds out that they have write access to other users' Firestore documents as long as they are signed in, will start deducting and taking coins from other users' wallets.
You will probably need to setup a server, or a script which will use Firebase Admin API to run transaction that you are talking about, so that it will be done in a black box according to your users' point of view.
Once you have the server up and running, client side app will then need to make calls to the server, preferably with auth tokens (e.g. Firebase Auth User's token), and ask for the transaction to run.

What happens to Firebase anonymous users?

I want to know what will happen to the users of my app that I used anonymous sign in method for them.
The Firebase documentation is really BAD and didn't explain everything and expect developer to find out himself.
I found in its old version documentation that anonymous session will expires based on the expiration time has been set in Login & Auth tab, but even there didn't mention this means just the session ends or it means that user id will remove also from my app users list or what EXACTLY happened?
I found this answer but it really is not acceptable. The number of anonymous users will grow very very fast if you do a web app and make every thing hard.
I even cannot see the number of my app users in my dashboard!!!!!
So, what should i do? should i develop a dashboard for my data myself or Firebase team should do it? At least for managing users i should have more power than just searching user with their email and when you use custom login you cannot do this also.
Anonymous users don't expire, and there isn't currently any automated way to purge them.
Firebase doesn't automatically remove them because it doesn't really know if a user is still storing data linked to that login - only the app creator does. Imagine if you are playing a puzzle game on your phone, and get to level 100. Then when you go to play level 101 next year, all progress is lost. Firebase can't just assume a user being inactive for a year means that the account can be removed.
There is a couple tools that should help, though.
1) Admin SDK & Firebase CLI list users.
2) Linking multiple auth providers
3) Auth State Persistence
Once you list your users, you can check that each doesn't have any other providers, and hasn't been used recently, doesn't have data stored, and delete them.
Better, though, would be to ensure that only one account is created per user. If you create an anonymous account to help users store data before logging in, you may want to consider prompting them to link a auth provider (like Google or email). If you link the account, rather than creating a new one, you'll avoid abandoned accounts from active users.
In general, you will also want to make sure to use auth state persistence to ensure that there aren't more accounts than necessary being created. Creating 1 account per new visitor, rather than 1 per time someone repeatedly visits your page, will significantly help keep user growth in check.
In my case, I am using the anonymous sign-in method for authentication without the knowledge of the user.
Each time when the user leaves the app, delete the anonymous user by -
FirebaseAuth.getinstance().currentuser?.delete()
There will be no stacking up of anonymous user with this and limits the number of anonymous user in the app
2023 update
Firebase has automatic clean up now.
If you've upgraded your project to Firebase
Authentication with Identity Platform, you can enable automatic
clean-up in the Firebase console. When you enable this feature you
allow, Firebase to automatically delete anonymous accounts older than
30 days. In projects with automatic clean-up enabled, anonymous
authentication will not count toward usage limits or billing quotas.
Any anonymous accounts created after enabling automatic clean-up might
be automatically deleted any time after 30 days post-creation.
Anonymous accounts created before enabling automatic clean-up will be
eligible for automatic deletion starting 30 days after enabling
automatic clean-up. If you turn automatic clean-up off, any anonymous
accounts scheduled to be deleted will remain scheduled to be deleted.
These accounts do not count toward usage limits or billing quotas. If
you "upgrade" an anonymous account by linking it to any sign-in
method, the account will not get automatically deleted. If you want to
see how many users will be affected before you enable this feature,
and you've upgraded your project to Firebase Authentication with
Identity Platform, you can filter by is_anon in Cloud Logging.
Docs
There is a possible cloud function for that.
Check: delete-unused-accounts-cron
This function deletes unused accounts after a certain time. Which might be also helpfull for nonanonymous users.
If you only want to delete anonymous users or check only for them (for example delete after a different inactive time than normal users) you can identify them by checking:
const inactiveUsers = result.users.filter(
user => {
isAnonymous = user.providerData.length == 0;
//do something when anonymous
});
If you'd like anonymous users to be removed from your user list, you'll have to write a service to do that for you.
Since firebase doesn't provide a way to list registered users, you'll have to make sure you're storing some sort of user list in the database. You can then use the node.js admin sdk to get user data, check if the user is anonymous, and find when the user was created. For performance reasons, you may wish to store this information in a special area of your database and retrieve it all at once. Once you've identified a stale anonymous user they can be easily deleted.

Resources