I have read this:
"Account linking can only be performed at the point at which a new
account is created. It is not possible, in other words, to link two
pre-existing accounts."
Is it still true?
I'd like this workflow :
User logs in the app and take his Anonymous uid;
Then User does the login (user previously registered) and obviously has his uid;
Now when the user does the logOut I'd like to give him his previous Anonymous uid, not a new one.
Is this possible?
It's not possible if you want to link your anonymous user to an existing account. It will give you an error: 'auth/credential-already-in-use'. You have to manually merge your two accounts.
It is possible to convert an anonymous account to a permanent account. You can do that by logging in the user into the new account, getting it's credential and then use it to link with the anonymous account, as mentioned on the documentation:
auth.currentUser.link(credential).then(function(user) {
console.log("Anonymous account successfully upgraded", user);
}, function(error) {
console.log("Error upgrading anonymous account", error);
});
But when the user logs out, he can't get that previous uid back. Because anonymous accounts are temporary, as mentioned on the documentation:
You can use Firebase Authentication to create and use temporary
anonymous accounts to authenticate with Firebase
And I think it makes sense. Because if a user was anonymous, it means he has no identification. So there's no way you can tell who was using that uid before.
Related
I'm building two Flutter apps that will use the same Firebase project.
The first app is public and used by users to create accounts, login and use the application within the allowed access rules.
The second is for admins to approve user posts.
You have to login to use both apps. With the first anyone can create an account and login. Admins can also login with the same admin account. But with the second only admin users should be able to login. I'm enforcing security via access rules. But I need the second admin app to reject non-admin users from login in in the first place. So I can't simply create a collection and put the admin user UIDs in it.
How do I differentiate regular users from admin users, and most importantly use that differentiation to disallow non-admin users from login in into the admin app?
Currently for login I'm simply using
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
I read about something called user claims, but there doesn't seem to be a way to modify this in the dashboard nor is there a way to specify some kind of condition via the code above.
I hope this makes enough sense.
Thank you all
You cannot prevent anyone from logging in to your application. The best you can do is check if the user is an admin. If yes, proceed else force logout them. You can use Firebase Custom Claims to add admin users or you can even store their UIDs in Firestore or Realtime Database.
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
// Check for claims here
if (admin) {
//...
} else {
await FirebaseAuth.instance.signOut();
// or just show alert that user is not an admin
}
You can use the getIdTokenResult method to get user's custom claims. This answer explains how to verify custom claims in Flutter.
The Firebase authentication documentation for Kotlin states that:
The call to linkWithCredential will fail if the credentials are already linked to another user account. In this situation, you must handle merging the accounts and associated data as appropriate for your app:
And then a code example is provided, the Flutter equivalent of which could be written as follows:
final prevUser = FirebaseAuth.instance.currentUser;
try {
final result = await FirebaseAuth.instance.signInWithCredential(credential);
final currentUser = result.user;
// Merge prevUser and currentUser accounts and data
// ...
} catch (e) {
// ...
}
Let's assume prevUser is an anonymous user. If the merge of prevUser and currentUser accounts and data doesn't succeed, is there any way to restore the Firebase sign-in state to what it was prior to the call to signInWithCredential, i.e. to make prevUser the currently signed in Firebase user again?
My app backend has its own representation of a user - AppUser - that is keyed by Firebase user uid, and there is an AppUser user that corresponds to (i.e. has the same uid as) prevUser. I don't want to recover from the failed merge by signing in anonymously, because that would give me a new anonymous user, with a different uid, which doesn't match up with said AppUser user.
No. Once an anonymous user signs out, or becomes replaced with a new sign-in, that anonymous account is effectively lost forever, from the perspective of the client app. The client app was the only holder of credentials that could perform a sign-in on that account.
You might want to consider at least persisting the uid of that account, then provide it to whatever process performs the merge. This would typically be done on a backend so that it could bypass any security restrictions on what can be done with an account when the user is not controlling it directly from a client app.
I'm currently developing a Flutter app for in a internal project whose process is :
You can log in as an authenticated user (mail / passwd) and complete some actions / tasks / validate things
You can log anonymously and complete some actions, BUT you need to validate these actions through an authenticated user (AU).
By doing so, each time an AU log himself, he can validate and then switch back to anonymous mode. The problem is that Firebase creates a new anonymous user each time.
The app could be utilized on multiple devices across the company, which could create 100's of anonymous users a day, while in fact it was only 6-7 users, so what can I do to avoid this ?
I've read about customIdToken but I haven't come to a solution for my problem.
Here is the code I'm using:
Future<FirebaseUser> signInAnonToken(String token) async {
FirebaseUser user = await _firebaseAuth.signInWithCustomToken(token: token);
return user;
}
FirebaseUser userAnon = await widget.auth.signInAnonToken("useranonuid");
Where "useranonuid" is the uid of the anonymous user but also the token I get by using the getIdToken(refresh:true) method
Thanks in advance.
The problem is that Firebase creates a new anonymous user each time.
The workaround that I did on my end is to add deleting the anonymous user on the end of each workflow. This should prevent the Firebase project hitting the 100 million anonymous user account limit.
There's no way to restore previous Firebase Anonymous Auth instance. That would defeat the purpose of being "anonymous" in the first place.
Convert an anonymous account to a permanent account
When an anonymous user signs up to your app, you might want to allow
them to continue their work with their new account—for example, you
might want to make the items the user added to their shopping cart
before they signed up available in their new account's shopping cart.
To do so, complete the following steps:
When the user signs up, complete the sign-in flow for the user's authentication provider up to, but not including, calling one of the
methods. For example, get the user's Google ID token, Facebook access
token, or email address and password.
Get an for the new authentication provider:
Pass the object to the sign-in user's method:
If the call to succeeds, the user's new account can access the anonymous account's Firebase data.
What does this mean as in what code is actually required (specifically to link an email/password to an anonymous account)? Note the above quoted text is quoted accurately.
I've tried this code but it does not work as expected:
firebase::auth::Auth* Auth = firebase::auth::Auth::GetAuth(App);
firebase::auth::User* User = Auth->current_user();
firebase::Future<firebase::auth::User*> Future =
User->is_anonymous() ?
User->LinkWithCredential(firebase::auth::EmailAuthProvider::GetCredential(email, password)) :
auth->CreateUserWithEmailAndPassword(email, password);
Heres my problem:
I wan't to be able to create new users for my website, from my website. This is only aloud though, if I have the "isAdmin" flag set to true in the realtime db under /users/myid.
Generally I would have done this with a security rule but the problem here is that I need to use the admin SDK, since the normal "createNewUser" method signs in to the newly created user automatically. I as an admin though, want to be able to create a new user and stay logged in as myself. So what I wan't to do is use ajax post request to my server with my uid und the new userdata which is to be created. My server then checks if the given uid has the isAdmin flag and if so creates the user with the firebase admin SDK which provides such a method.
But, anyone, if they have an admins uid, could hit up that request and create a new user. (My clients definetely get uid's from other users).
So how would I go about proving to the server that I am actually logged in with that uid.
From my understanding, tokens are used to be able to write to the database, but I don't need that permission, I just need to prove that I'm actually logged in with that uid.
Is there something I'm missing? Thanks a lot guys!
Was easier then I thought. This will generate a token on the client side:
firebase.auth().currentUser.getToken(true).then(function(token) {
// send request to server with generated token
}).catch(function(error) {
// handle error
});
Which I can then verify on the server like so:
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
// user is logged in
}).catch(function(error) {
// user is not logged in, or other error occured
});
Taken from https://firebase.google.com/docs/auth/admin/verify-id-tokens