When the user logs into my app, I want to store his UID somewhere in the app because I do certain offline functionalities with the UID. My requirement is that, once he logs in, I should be able to store the UID somewhere by retrieving it from firebase. Once that is done, unless he logs out, I need to be able to access this UID locally on the app to certain processes from various different activities. Only when he logs out, this UID can be deleted. If he quits the app, or the internet connection is lost, my ability to access this UID string shouldn't be affected. What is the best place to store this UID?
Firebase Auth already takes care of keeping the UID at all times for you. You can access it using the code showed on the documentation:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is logged in
String uid = user.getUid(); //this is the stored uid
} else {
// User is logged out
}
Related
On the application I am developing, the user creates their account with e-mail and password but how can I make data specific to the user? For example, in my application a user can gain points by completing certain tasks. So when a user completes a task, I need to update their points and store it on the database so they can gain points overtime and use them to redeem awards. Here is what I think I am supposed to do, but I am unsure if I have to add anything to the rules or not.
Note: Every user's point amount is supposed to be unique to that specific user
If you want users to only be able to read/write their own data, you'll want to store that data under the user's UID. From the Firebase documentation on securely accessing user data:
Another common pattern is to make sure users can only read and write their own data:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}
👍 yup looks good, just be careful about who has access to write to that document.
I have developed an app on Android that uses the Firebase realtime database. aka multiple nodes in the DB store various data collected by my app. For Auth, email/password-based Sign-in and Sign-up are working properly. When I sign-up a new user the auth works but that new user then needs to be granted access to the firebase database nodes the app uses. My app needs to grant this new user access to the firebase database nodes required for app interaction.
In other words, how do I programmatically, via my app, change the firebase node-access/security rules in my app (when I currently only know how to change these via the Firebase browser UI)? I do not see methods in FirebaseAuth to do this. So, where do I go from here?
Also, obviously a new user of my app will not have my credentials but they must be able to add access for themselves to my existing firebase realtime database nodes. How do I this?
Here are the rules I have in place today (where my UID is my actual firebase UID):
{
"rules": {
".read": "auth.uid === my UID",
".write": "auth.uid === my UID"
}
}
I now understand I must set rules to allow all authenticated users to read write data in various nodes of my tree. I do not yet understand how to grant access by node and particularly by a specific uid-based node in a tree where there may be many UIDs for each user. As an example, if my tree is root (top), then messages, then a UID for each user, what is the syntax for an authorization rule that will allow the current user/UID read/write the data in only his/her UID under root, messages, his/her user UID?
I have a Login System implemented using Firebase Auth, But Whenever I Disable any user he/she can still be logged.
But When he/she log out and login him/her by themselves, then the disable system is working.
So what should I do to check every time, whether a user is disabled or not?
Is there any function or something?
Thanks.
Edit: 20th April 2022
Since the answer is some kind of old, I'll add another approach that we have nowadays, which is by calling FirebaseUser#reload() method, which:
Manually refreshes the data of the current user (for example, attached providers, display name, and so on).
So when calling the reload() method, it means that we reload the user's profile data from the Firebase server. Another thing to mention is that a FirebaseAuthInvalidUserException will be thrown if:
The current user's account has been disabled or deleted, or its credentials are no longer valid.
But remember, this also doesn't mean that auth state is changed. You need to call this method explicitly, for example, when the user opens the app. Also remember, that the method is asynchronous, it returns a Task object. So you need to attach a listener in order to get the new profile data from the server.
If you disable or delete a user account does not mean that it also fires an auth state change. Nor should it, because the user is still authenticated in the application. You need to know that in at most an hour, Firebase Authentication will try to refresh the access token for that particular user that was disabled or deleted. But in this case, that refresh will fail, at which point the user will become unauthenticated. This is the point at which the auth state change event will fire.
If you want to revoke the user's authorization immediately, you'll have to do so in another part of your application logic. A common practice when it comes to Firebase is to create a new node in your database called blacklist that should look like this:
Firebase-root
|
--- bannedUsers
|
uidOfBannedUser: true
Now when you delete/disable a user's account in your Firebase console, you also need to add the corresponding UID to the list of banned users in the database.
The database can then be secured against access from unauthorized users with the help of Firebase Database Security Rules. This can be done by adding a clause to your database security rules like this:
{
"rules": {
"bannedUsers": {
".read": true,
".write": false // only admins can write these
},
"messages": {
".read": "auth != null && !root.child('bannedUsers').child(auth.uid).exists()"
}
}
}
If you use a different back-end, the implementation will be different. There can be orher more examples but a blacklist like this is a common approach to ban users. You'll find that you may even care little enough about their authentication that you only ban them, instead of deleting their credentials, which they could simply recreate.
You can check the state by FirebaseAuth.getInstance().getCurrentUser().reload(); or FirebaseUser.reload() - The code Manually refreshes the data of the current user (for example, attached providers, display name, and so on).
In Android Java, if 1st the email account is disabled in Firebase Authentication Dashboard && (2nd) in your Android code the above .reload() is made, then the next FirebaseAuth.getInstance().getCurrentUser(); call will return a null.
OR
FirebaseAuthInvalidUserException thrown if the current user's account has been disabled, deleted, or its credentials are no longer valid
Use theFirebaseUser.reload() with an onCompleteListener and if this listener returns a failure, display a prompt and sign the user out or move to a login page
I have authenticated my user using phone authentication, and the user object that is returned has this long string when I call user.getUid() :
dn27dhJK..... (some long string).
If I authenticate this user on some other device (using my phone number etc), will user.getUid() always be the same ?
EDIT: From the documentation: https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseUser
public abstract String getUid ()
Also: Google Play services Returns a string used to uniquely identify
your user in your Firebase project's user database. Use it when
storing information in Firebase Database or Storage, or even in your
own backend.
This identifier is opaque and does not correspond necessarily to the
user's email address or any other field.
It is unclear if this id remains constant or not.
When you first verify the phone number (or first sign in with a social provider, or call createUser), a user account is created - and thus a new unique UID id created. From that moment on, that user/phone number will remain associated with that account/UID. No matter if they re-verify on the same or a different device.
If you delete the account, a new account+UID will be generated when you use that same phone number next time.
If you're using Firebase Authentication in your project:
Remember
Firebase will generate a single unique key(i.e. UID) on registration of a/c whether using Email/Phone number.
This key remain associated to that a/c untill a/c is exist in firebase authentication list.
If your app is uninstalled on phone & then a/c is open in another then we can fetch that key from Firebase cloud auth. service.( UID remain safe).
This Uid is created when the user signs up and is linked to the phone number that you used. When you sign in you will get the same uid. But if you try to sign up again with the same phone number, it will basically give an error saying this phone number is already signed up.Hope that explains!
I am using Firebase in my android app.
My purpose is that the a user of the application should be able to write data to the database but I don't want the user to sign up so i am using anonymous sign in.
I have a form that the user can submit and will be committed to database. At the time of submitting it is possible that the anonymous sign-in may not have been done. Is it possible in Firebase that I call the write instruction to the database and it is written locally and commits the moment the user is signed in anonymously?
I know that Firebase does provide offline capabilities. But I assume if i were to call write database before signing in, it would give me an error.
I had the same concern when developing an application. If a user had their phone in airplane mode or were offline at first launch, it was possible they could reach a point where they needed to save data before the anonymous authentication completed successfully.
A workaround is to create an "unauthenticated" tree in your database that is writable by anyone, but readable only once authenticated. When the user is authenticated you can copy the data to an appropriate location and delete any data written in the unauthenticated area. You can queue up data to be written and Firebase will automatically write when the user is online.
The trick is to get a push id in the unauthenticated tree that you will use as a temporary user id. This value should be persisted locally using SharedPreferences or another method of your choosing.
db = FirebaseDatabase.getInstance();
db.setPersistenceEnabled(true);
dbRef = db.getReference();
// This key should be saved on the user's device until authenticated
String key = dbRef.child("unauthenticated").push().getKey();
// Write some data
dbRef.child("unauthenticated").child(key)
.child("somedata").setValue("testing");
Any writes that you make to this child will be persisted as soon as the network connection becomes available. Attaching a listener to this temporary key might look something like below...
dbRef.child("unauthenticated").child(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("DB", "Got value from database: " + dataSnapshot.child("somedata").getValue());
if(FirebaseAuth.getInstance().getCurrentUser() != null) {
/** If user is authenticated, move data to authenticated location **/
}
}
#Override public void onCancelled(DatabaseError databaseError) {}
});