Uploading and updating position anonymously on Firebase - firebase

So, what I want to do is for users to upload their positions to Firebase under a known key (so that the uploader can update his position), but anonymously.
When I use .push(), I do get a "unique" key, but I can't get the reference to update the position later.
If I use an uid, users are going to have access to other user's uids and I'm afraid this could be a security breach. (I'm not sure if uids are very relevant security-wise).
What can I do to post anonymous positions and update these fields later?

Firebase Authentication UID strings are not intended to be secure or private. The only security is provided by security rules on the data you wish to protect. If one user knows another user's UID, they don't know the identity of the person on the other side, unless you manage to leak that data by failing to protected it correctly with security rules. So be sure to define what your access rules should be, and implement them accordingly.
If you want to use a push id for any reason, just be sure to store that unique string somewhere so you can use it later to construct a ref to the path where it was added.

Related

Does createCustomToken(aUID) logout users currently authenticated with that same aUID

TLDR; Can multiple different users be authenticated and retain authentication via a generated custom token IF that custom token for each of those users is being generated always by the same UID? That is, User1 gets custom token generated by UID1 (via createCustomToken(UID1)) and then signed-in with signInWithCustomToken(), THEN User2 gets and signs-in with custom token generated using UID1, then User3 same thing etc etc, can ALL these users happily remained logged-in and experience no interruptions despite these other users being authenticated in this identical manner?
Long Version:
Ok, so I am trying to create a link-sharing system wherein a user who navs to this link can access a specific subset of my project's Firebase resources.
I have already tried using Firebase's signInAnonymously() to do this, but I dont like the way that Firebase does this for a whole host of reasons I dont want to get into.
The way i want to accomplish this is by:
generating a unique link (really a Firestore unique doc ID with some access data stored in that doc)
having the unauthenticated user navigate to some landing page, calling the cloud function and passing that unique link (lets call it a UID now)
cloud function, upon recieving this UID, will createCustomToken(UID), returning the token back to calling user
and the user will authenticate themselves with signInWithCustomToken(returnedToken) and access provisioned resources
Now, that is all well and good, but my question is:
If two (or any amount more people) people navigate to that same link and therefore pass and create token with the same UID, will they all be ok to continue happily using Firebase resources? Or is it because they got tokens created for them which utilised the same UID a sort of token-conflict is made, and therefore any next user who authenticates in this manner will revoke the previous user's auth token.
I havent been able to try this, and it seems like every question asked about these custom tokens relates to the generation and expiry time of them, which I understand. I wish the Auth docs were more clear on the mechnics and pitfalls of using Custom Tokens. I also havent been able to try it myself as it would be quite alot of refactoring, and was hoping someone could give me a straight answer to this.
Yes, a user can login on multiple devices without affecting other sessions at the same time irrespective of which auth method you use.
I'm not sure what the unique links are but it's not a good idea to pass the UID itself around if you function just takes a UID and returns a custom token as UIDs are pretty short and just a random string. It might be best to add a custom signed JWT in the links that contain the UID in payload so you can verify them before creating Firebase Custom Tokens.

Have one user signup another user with custom fields in firebase/flutter

I am trying to determine if the following scenario is possible with flutter and firebase:
we have users within the company who will be given access to the app, where on the homepage will be a signup another user button where they enter in that user's email and password, they get signed up, and then the original user specifies custom fields for the 2nd user, such as company name, role, position, etc.
Is this possible with flutter and firebase?
Have asked the flutter google group and was told about custom authentications, but from what I see that is just an external authentication system and doesn't show me how to let one user create another users profile with fields.
Any ideas?
The first thing to consider is whether those properties need to be in the user profile at all. The user profile is sent with every request, and should only contain information that is relevant for securing access. If you have additional information to store about the user, you should store it elsewhere (such as in one of Firebase's databases) using the UID of each user as its key.
Assuming that the information is about security (such as the role seems to be, there is no secure way to let one user set security properties (typically referred to as claims) from client-side code. As soon as this is allowed from client-side code, anyone could set such properties for anyone else. That's why setting custom claims for a user is only possible with Firebase's Admin SDKs, which are designed to run in a trusted environment - such as your development machine, a server you control, or Cloud Functions.
There are a few other options, but it's important to realize they're all implemented on top of the above approach.
There is an experimental extension that allows you to set auth claims by writing a document into Firestore, which something like this (JavaScript syntax, but the Flutter code will be similar):
db.collection("user_claims")
.doc("abc123")
.set({
role: "admin",
groups: ["example1", "example2"],
});
Now of course you'll want to make sure that you secure writing to the user_claims collection, as otherwise you'll end up with the same security risk I mentioned in the first paragraph, where everyone can claim any role they want.
Alternatively you can write your own server-side API (for example on Cloud Functions) that you expose to your application, and that then calls the Admin SDK. Here too, it is important to secure access to this API, to ensure only authorized users can call it.

Do users need to create an account to read/write to Firebase

I'm making an app that has Firebase as its database. The app shouldn't need the user to create an account to use it, but I want the user to be able to read/write their data onto the database (so maybe they have to create an account?).
Do I have to make the users create an account in order to use Firebase?
My problem is that my security rules are read/write are allowed for everyone (which I know is wrong, but how do I change them and not need users to create an account?) Maybe that's the issue.
It is best to ask them to create an account
Although:
it can be a non-real email address and
there is anonymous auth also available
It sounds like you need the app to remember that user's particular data, so that when they return to the app, it is still their data (and not someone else's) that is being accessed.
To achieve that, we need each person's data to be stored in a different place in Firebase. Traditionally, this is by having them log in to some kind of system, most conveniently Firebase itself, and then the data stored in a branch of the database defined by their user Id.
Without logging in, you could simply ask the user for an identifier, such as "Bob" or "Carol", and then store their data under their identifier. The Firebase database would therefore have the following structure.
users/Bob/highScore: 3000
users/Bob/level: 7
users/Carol/highScore: 5050
users/Carol/level: 9
However this is not secure because there is nothing stopping Carol coming to the app and saying she is "Bob". Any such client-side activity you carry out to attempt to identify the user is not really authentication (in the opinion of Firebase) because all client-side activities can be faked relatively easily.
Firebase Authentication
The standard solution is to use Firebase to authenticate each user (see the Firebase authentication docs for this), and give your app a user Id (such as "8769dsg6f8g7698769876sdgs9") which is unique and known (by Firebase) to be correct.
Firebase security rules
You can then lock down the database using Firebase Security Rules so that only user 8769dsg6f8g7698769876sdgs9 can write to any of the users/8769dsg6f8g7698769876sdgs9/.... part of the database.
If you don't use Firebase to authenticate the user, Firebase will treat the user as unauthenticated and you will have no way to restrict each user to their own section of the database. Either you leave it wide open (to hackers etc!) or users will not be able to access their own personal data on it.
They can use a FAKE email address and password
If your concern is that they won't want to give out their real email address, you can ask them to make up any email address, e.g. mickeyMouse49857430679304#hotmail.com, and set a password. There is no obligation on your app to contact them on that email address or verify that the email address is correct.
Whenever they come back to the app, or access it on another device, they need to remember the fake email address and password.
Of course, if they lose their password, there is no way to reset it.
Anonymous Authentication, but at risk of losing access
The legendary Frank von Puffelen of Firebase, himself, has added a remark about Anonymous Authentication, in the comments below. From what I understand, this avoids them having to make up a fake email address.
I think the weakness of this is that if they lose their local web storage (e.g. if they manually wipe it, or move to another device), there is no way for them to re-access the same account, unless they have planned ahead by adding an email/pw to the anonymous account.
The only real way to have security per-user data storage is to use Firebase Auth to sign in the user, and write security rules to protect the database so that each user can only access their own data. There are no secure alternatives to this for Realtime Database.

Use a username as key in firebase for storing users

I want to have a username/password login system instead of email/password. What I am currently doing, is to take the username and append a '#domain.com' at the end and register the user on firebase as an email/password account.
In my firebase database, I am storing the user information under 'userProfiles/$uid'. However, given only the username of a user, I need to first access another node to lookup the uid and then use that to access the user data.
My question is: are there any disadvantages in just storing the user data under each username instead? In my security rules, I can then do this:
$username + '#domain.com' === auth.token.email
Most of the time, I have direct access to the user's uid. However, there is the case where I want to reset a user's password(I had to implement it myself because I am using the usernames as emails in firebase) and I only have access to the username.
Update
As pointed out in the comments since users are being signed up using username + '#domain.com' Firebase will prevent duplicate usernames because it won't allow two separate users to sign up with the same email. Once your user is created you can write the username to the database and there won't be any collisions. Keep in mind that this problem can become more difficult if users are allowed to change their username. You'll have to check the newly requested username against the existing usernames to determine if the requested name already exists. Lastly, don't forget Firebase is case sensitive so you might want to cast all usernames to lower/uppercase and trim the trailing white space before you upload them.
The biggest problem I can think of is that uid's are guaranteed to be unique by Firebase so there can't be any duplicates. If you store everything by username you'll have to make sure there are no duplicate usernames when users sign up. So you have to make an area of the database that can be read from by unauthenticated users to check the requested username against existing usernames.
You have to think about how you're going to access the data most of the time. Additionally, if you denormalize the user data (store it under uid & username) you have to make sure that both copies stay in sync. It's probably easier to just store username -> uid so that you have a mapping to get to the user data if you only have the username. This isn't going to happen that often and the extra nested query isn't going to make much of a performance difference.

Is it possible to access provider-specific data of logged-in users in Firebase security rules?

If a user logs into my Firebase store with Google authentication, the client gets access to all sorts of useful user-specific information, like the user's name and email. I might want to put this information in the store, and the client can certainly send it along in a write request. But as far as I know, there's no way to validate (on the server side) that this information is correct. There is nothing stopping someone from using a second client to send fictitious metadata.
(For instance, take a look at the skeletal auth variable which is accessible from security rules. It doesn't contain the information I need for validation.)
How do people deal with this kind of situation?
Only limited information about the user is available in the auth variable in security rules.
To access more information, you'll have to store that information in the database when the user is created or signs in. Most developers add a /users node to their database for this reason.
You can then look the extra information up in your security rules with something like root.child('users').child(auth.uid)...
The process is covered in the Firebase documentation section on Storing User Data.

Resources