Firebase - userId keeps changing - java

In an Android project I use Firebase with signInAnonymously() and I am getting userId like this
userId = FirebaseAuth.getInstance().getCurrentUser().getUid()
and I use the userId to create children nodes in Firebase Realtime Database that only this user can access based on the access rules of that database.
The problem is that I noticed userId changes randomly and when that happens all content created by that user is lost to them. Is there something I can do to keep the same userId until the app is uninstalled? What other way can I use to ensure steady and exclusive access for that user to a Realtime database child? Can installation id be used?

You can use Firebase Anonymous Authentication to create and use only temporary accounts to authenticate with Firebase. The Anonymous Authentication accounts don't persist across application uninstalls. When an application is uninstalled, everything that was saved locally will be wiped out, including the anonymous auth token that identifies that account. So there is no way you can reclaim that token for the user. So each time you sign in, a new UID is generated.
What other way can I use to ensure steady and exclusive access for that user to a Realtime Database child?
To always have the same UID, then you have to implement the Firebase Authentication with a provider like Google, Facebook, Twitter, and so on.

Related

Firebase multiple login method but single user profile

Oo currently I am trying to check and see if its possible to do a single user profile account using firebase authentication under my android project , but here is the kicker which is it should allow me to let my user login using either email, facebook, google, GitHub , etc. from their choosing but after authentication of it, the user is still under 1 account profile, and not separate or a different profile as an example.
sample email from the user :
1. user_gorilla#gmail.com
2. user_apple#yahoo.com
3. hotstuff#hotmail.com
4. this_is_not_a_joke#gmail.com
all of that login and email is just from 1 user and I would want them to have just 1 profile, but enable them to login using multiple emails.
is there currently an in-app function in firebase that does this? or do I have to do and make it myself? because I am currently thinking of doing something along the lines of.
User_profile <- collection name
UID:UID <- this should be the unique document ID
Fullname:
Emails: <-- separate set of collections where the emails for the specific user is stored.
so this is how it goes when the user is created and signed up, the admin still needs to verify "if" the user already has been made inside the collection of user_profile, and if not then the admin would need to create the user_profile and then give the user their unique ID/key.
each time the user creates a new login credentials/authentication login , they need to register it into the admin so that the UI for the profile will show up for the newly created authentication for the user but would still reflect the old profile of the user , its just that the profile gets updated every time and needs to be added by the admin to do so.
would this work out? or does firebase already have something like this kind of function?
so currently i am trying to check and see if its possible to do a single user profile account using firebase authentication under my android project
According to the official documentation regarding Link Multiple Auth Providers to an Account on Android:
You can allow users to sign in to your app using multiple authentication providers by linking auth provider credentials to an existing user account. Users are identifiable by the same Firebase user ID regardless of the authentication provider they used to sign in.
So the key to using this feature is to have the same Firebase user ID.
here is the kicker which is it should allow me to let my user login using either email , facebook , google , github , etc.
Currently, the sign-in methods that are allowed are:
Email/Password
Phone
Google
Play Games
Game Center (Beta)
Facebook
Twitter
GitHub
Yahoo
Microsoft
Or even an Anonymous authentication.
from their choosing but after authentication of it, the user is still under 1 account profile , and not separate or a different profile
For example, a user who signed in with a password can link a Google account and sign in with either method in the future.
What you can't do, is to have users like:
user_gorilla#gmail.com
user_apple#yahoo.com
hotstuff#hotmail.com
this_is_not_a_joke#gmail.com
With different Firebase user ID and link them together. Even if they are the same users, without having the same Firebase user ID, there isn't much to do.
is there currently an in app function in firebase that does this?
No, there is not. If you want to have all those users under a single account, you should create your own mechanism.
or do i have to do and make it myself?
Yes, you need to write code for that. You should match those accounts and somehow convert them into a single one.
or does firebase already have something like this kind of function?
No, it doesn't. The only viable option that you have is to link their multiple accounts using auth provider credentials to a single user account.

Firebase: How to manage UI changes during queued writes?

I use the Firebase realtime database in my Android app where disk persistence is enabled.
When the user opens the app for the first time I read auth status, if that is null I show the login screen and after the login, I will get the username stored against this user id in the realtime database.
If the username is null then I will show username setup screen where he will choose the unique username for him. The problem arises when the connection goes off during the username setup phase. username is not yet written to the database but when he opens the app next time username will not be null as Real-time database gives me value stored in the cache. So I proceed to the home screen but what if someone else chooses the same username during this phase?
I maintain two-way mapping between uid and username as suggested in this answer
I can't use transaction because at a time transcation can be run only on one path but in my case, I have to automatically update two paths.
I also have security rules setup up for maintaining unique username but what to do with the users who are already crossed the username setup screen.
What if someone else chooses the same username during this phase?
Everytime you want to perform a write operation for a user name, you need to make sure it's unique. To check if a user name exists in a Firebase realtime database, a query like this is required:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("users").orderByChild("userName").equalTo(userName);
query.addValueEventListener(/* ... */);
So if the user tries to set/change the user name while offline, the above query is added to a queue. Once the user regains the connection, every change that is made while offline, will be updated on Firebase servers. With other words, the above query will be commited on the server. So if a user chooses a user name that already exists in the database while offline, when is back online, he'll receive a message that user name already exists.
I can't use transaction because at a time transcation can be run only on one path but in my case, I have to automatically update two paths.
I cannot use transaction because it can be run only on one path, you cannot use transactions at all. Transactions are not supported for offline use. This is because a transaction absolutely requires round trip communications with server in order to ensure that the code inside the transaction completes successfully. So, transactions can only execute when you are online.

FirebaseAuth - Replication of a modifed user login/email

Changing the email address of the currently logged in user works just fine using the updateEmail method of the user object, however it appears as if that change is not replicated to other logins, which still keep the previous email address.
Is there any notification I need to subscribe to / catch in order to be notified by such a change or is there another way to accomplish that?
Me, as a long time Firebaser, I read the docs a lot, like a lot. And I do have a workaround for this since there aren’t any built in.
First, if you provide multiple sessions per user, you’d want to use the reauthenticate method.
Re-authenticate a user
Some security-sensitive actions—such as deleting an account, setting a
primary email address, and changing a password—require that the user
has recently signed in. If you perform one of these actions, and the
user signed in too long ago, the action fails with the
FIRAuthErrorCodeCredentialTooOld error. When this happens,
re-authenticate the user by getting new sign-in credentials from the
user and passing the credentials to reauthenticate. For example:
let user = Auth.auth().currentUser
var credential: AuthCredential
// Prompt the user to re-provide their sign-in credentials
user?.reauthenticate(with: credential) { error in
if let error = error {
// An error happened.
} else {
// User re-authenticated.
}
}
Using this, you’d get the error 90% percent of the time because of old credentials.
Or:
(1) On the change process. Set a specific key for the user on your real-time database or Firestore,
(2) Check for that specific key on your app, if existed. That means the user needs to be re authenticated. Firebase will update the user credential on every new login.
I hope it helps.
Here’s the docs:
Manage users on Firebase

Android Billing how to use setAccountId or assign payment to custom identifier

I would like to **allow my users using my app across multiple devices **. Users have to log into my app through firebase auth.
Problem is that payments are assigned to account that is signed on the device (google play), not with account signed into the app.** From firebase auth I can get an email address of the user of my app - this could be used as some unique identifier.
Problem visualized:
I noticed that in Billing flow there is .setAccountId("some id") I think I could use this to fill in a unique identifier of a user. But how can use it querying purchases?
BillingFlowParams.Builder builder = new BillingFlowParams.Builder()
.setAccountId("some id")
.setSku(PREMIUM_YEAR_SUBS).setType(BillingClient.SkuType.SUBS);
TLDR: All I want to do is to retrieve purchases that are connected to my APP user account, not device account (google play currently logged in user).
To implement billing using accountId, try using the getBuyIntentExtraParams() method which provides additional functionality as compared with getBuyIntent() method.
With this method, you may use accountId with the following description:
Optional obfuscated string that is uniquely associated with the user's account in your app. If you pass this value, Google Play can use it to detect irregular activity, such as many devices making purchases on the same account in a short period of time.
Additionally, you may want to also check the typical purchase flow with the In-app Billing API discussed here.
It seems that we can't get the accountId, the accountId just used by google play.
I guess that you use the accountId to instead of the payload, but after my try, I think that it is not successful.
In the Google Billing Library, the develop payload is removed for the same experience between the in-app-purchase and the out-app-purchase. Though we can add payload in the period of consume or acknowledge, but it useless. And the payload should be set on the period of purchase, but google delete it, and will not be add back. The payload issues.
You can check the AccountId attached to each Purchase using
Purchase.getAccountIdentifiers
It'll return AccountIdentifiers object that has
AccountId & ProfileId that were set previously in BillingFlowParams when you launched billing flow
After that you can compare the current user account id with the account id attached to each purchase
to detect the purchases that are connected to the current user account

Send RegistrationId To Backend

I am following the Client side GCM code on the Android dev site; I came across this:
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
Now this questions is not WHAT to implement there, I know how to do httpost's and send param's to the server.
My questions is WHERE do I send this in my Database?
I am implementing GCM in an app that already has registered users, so I have a users MySQL table. Now here are my questions: From what I have read, do RegistrationId's have a unique relationship with a user? If so, can I just put the RegistrationId for the user into a new column in my users table? The only issue I see: What if the user uses the app on multiple devices. So that makes me think my logic is wrong. And if it is wrong...
..should I just do what I have seen in demos and put registration ID's in their own table -- and if so, should they be put there with the user Id in the same row so that a reg Id can be identified to a particular user (not just device)?
The relation between a user and a Registration ID is many-to-many :
As you realized, if a user has multiple devices, that user would be associated with multiple Registration IDs.
If on a single device one user logs out and another user logs in, both would be associated with the same Registration ID. In that case, however, you can cancel the association of the Registration ID to the old user before associating it with the new user. This would simplify the relation between a user and a Registration ID to one-to-many.
Given those two points, having a table that contains for each Registration ID a user ID would work. Just don't forget to remove entries from this table when users log out, since when a user logs out in a specific device, the Registration ID that what given to that instance of the app is no longer associated with that user.
It depends on what your app wants to do:
If the user will use only one device you can put it in the user table.
If the user can have many devices and the same notifications should be sent to all of them you can have a list of registration ids for each user (a one to many table).
If each device will have different notifications you should add a table for the devices, and add the registration id there.
You could also group the registration IDs related to a single user using the notification key.
http://developer.android.com/google/gcm/notifications.html
That way you have one entry per user and you only need to send one message per user, GCM takes care of the rest.

Categories

Resources