Skip to content

Anonymous user and account conversion to permanent account #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
danielkummer opened this issue May 19, 2016 · 100 comments
Closed

Anonymous user and account conversion to permanent account #123

danielkummer opened this issue May 19, 2016 · 100 comments

Comments

@danielkummer
Copy link

Hi there

Is there a way in which AuthUI supports the conversion of a anonymous account to a permanent one (one of the supplied auth providers)
As stated in the documentation and as I understand it, one must use the linkWithCredential method instead of the "normal" signInWith flow.

Can this be done with the current AuthUI version somehow?

@iainmcgin
Copy link
Contributor

Hi Daniel,

We don't have any direct support in FirebaseUI for upgrading anonymous accounts to an account backed by an authentication method just yet. You can do it directly with the Firebase Auth APIs, see here in the section "Convert an anonymous account to a permanent account".

I'll leave this issue open as a feature enhancement request; we can likely handle this automatically within FirebaseUI if an existing anonymous user is present in auth.getCurrentUser() when sign in occurs during the authentication flow.

@danielkummer
Copy link
Author

Hi @iainmcgin - thanks for your reply (and considering it as a feature enhancement :) )

I've read through the documentation you mentioned - maybe you can answer me this: Is there a way to get the AuthCredential object from AuthUI which was used by the user to sign-in? As I'm reading the docs, without this object instantiated with the users credentials there's not way to link accounts...

@iainmcgin
Copy link
Contributor

Ah, we have a slight problem here after discussing this with some colleagues. There is deliberately no way to get back an AuthCredential from an existing user, to avoid potentially leaking credentials. So, the linking of the authentication method to the anonymous account would have to occur within Firebase UI if you are using the library. I'll take a look at this next week to get you unblocked ASAP.

@danielkummer
Copy link
Author

Great - looking forward to hearing from you 👍 (And thanks a lot!)

@guillermomuntaner
Copy link

guillermomuntaner commented Jun 9, 2016

Facing similar case. My app uses default anonymous login to provide a frictionless experience while being able to store user data. Log-in (non anonymously) is a secondary optional feature if the user wants to save his data between devices or access specific features. So my app doesn't really have a true logout status and instead rely on anon/non-anon statuses.

1 - Simple scenario;
An anonymous user with some local data decides to sign up with X provider (new account). In this case FirebaseUI creates a new user instead of linking the new credentials to the current anonymous user. Moreover the new user is loged in without a warning, so the anon user is lost for ever. ¿Wouldn't be a good default behaviour to try to link the credentials first? In case an account for those credentials already exists linkWithCredential will return an exception which can be handled as follow (see scenario 2)

2 - Complex scenario:
An anonymous user tries to sign in (to an existing account). In this scenario we have 2 users and I guess it should be managed by the developer. So some sort of callback/result.

I see how this is problematic due to the potential complexity of second case, but at least the 1st case can be solved very easily by trying to link 1st new credentials when an anonymous user is in.

@drewhannay
Copy link

@iainmcgin Any updates on this? I'm blocked on the same issue and wondering if I will need to fork FirebaseUI to proceed...

@pcarbonn
Copy link

pcarbonn commented Jul 6, 2016

Same issue here ! Waiting for a fix...
In fact, I'm using firebase oauth for a web app, so I'll post in the relevant github project.

@janakagamini
Copy link

I'm quite keen on this feature too.

@pantos27
Copy link

Looking forward for this enhancement
on both Android and iOS

@shalama
Copy link

shalama commented Aug 29, 2016

Has this feature been implemented in the 0.5.1 release? I'm also really looking forward for this.

@samtstern
Copy link
Contributor

@shalama this has not been implemented yet. It's something we are looking into for future releases though.

You can see exactly what changes with each release by visiting the release notes:
https://github.com/firebase/FirebaseUI-Android/releases

@GaborPeto
Copy link

+1 for the feature request

@bobshao
Copy link

bobshao commented Dec 8, 2016

Hi @iainmcgin , we have the same feature requirement. Does team have any workaround for this? Hope you can have a response :)

@SUPERCILEX
Copy link
Collaborator

@bobshao Unfortunately, there aren't any workarounds as mentioned above, but I'm going to be able to work on #309 again so I'm hoping for it to cut FirebaseUI v1.1.0 which will be coming out soon.

@bobshao
Copy link

bobshao commented Dec 8, 2016

Thanks very much for your quick response :) @SUPERCILEX

@curiousily
Copy link

It looks like 1.1.0 is shaping up at #510. Will #309 be included in the version?

@samtstern
Copy link
Contributor

@curiousily this will not be making it into the 1.1.0 release due to cross-platform issues. We don't have an implementation on iOS yet.

@curiousily
Copy link

@samtstern thanks for the info. Will love to hear any plans concerning when this will be merged.

@percula
Copy link

percula commented Feb 6, 2017

Any progress on this? This feature would be great for an app I'm working on.

@SUPERCILEX
Copy link
Collaborator

@percula #309 is ready to be merged, but it's waiting on firebase/FirebaseUI-iOS#139.

@percula
Copy link

percula commented Feb 7, 2017

Thanks @SUPERCILEX ! Looks like there's good activity on the iOS side now.

Beginner question: I want to use your implementation of Anonymous Auth linking, so I cloned your fork. Then I followed the instructions to install the repository to Maven Local ./gradlew :library:prepareArtifacts :library:publishAllToMavenLocal. Now, how do I add your fork as a dependency in Gradle and make sure that I'm getting the fork and not the master FirebaseUI? I currently have: compile 'com.firebaseui:firebase-ui-auth:1.1.1', but don't think that's right.

@samtstern
Copy link
Contributor

@percula if you change the version number in constants.gradle and then install locally again you can be sure you have the local version.

@SUPERCILEX
Copy link
Collaborator

SUPERCILEX commented Feb 7, 2017

@percula @samtstern Whoa whoa whoa, you guys aren't being lazy enough! 😄 I would just use JitPack if I were you. Once you follow step one on their website (add the maven reop), you can just add my fork like so:

compile 'com.github.SUPERCILEX.FirebaseUI-Android:firebase-ui-auth:d1df8d2c0aef03f3db008d4021059ba316386c7c'

That's way easier to start and to keep yourself up to date with my fork. Cheers! 🎉

@samtstern
Copy link
Contributor

@SUPERCILEX I can't believe Jitpack works with our crazy build system. Very impressive.

@SUPERCILEX
Copy link
Collaborator

@samtstern Yeah, it took a while for me to figure out, but it would have been too much of a pain to re-compile everything every time I wanted to test it in my own app. Basically because we have several modules, instead of com.github.SUPERCILEX:FirebaseUI-Android:version we have to use com.github.SUPERCILEX.FirebaseUI-Android:firebase-ui:version.

@SUPERCILEX
Copy link
Collaborator

@j2emanue You can't and this is acceptable behavior. I agree that it triggers our internal developer's need for cleanliness, but there's no nice way to ensure the account has been fully migrated and also delete the account. (By the time the migration is done, it's too late to delete the account.) Sorry for not being able to provide a better answer! 😊

@GuanacoDevs
Copy link

What I'm doing at the moment to sort this out is to use firebase functions to delete the anonymous user, and copy/delete(Anonymous) its current data in case of a new sign in or just delete the anonymous user data in case of concurrent signin.
I have a property "anonymous_user_uid" in my user data which triggers a function, after the "Write" function has finished it deletes the "anonymous_user_uid" related to that uid.

@SUPERCILEX
Copy link
Collaborator

Thanks for sharing, that's a cool idea! Not something we can do in the library, but good to know as individual developers.

@j2emanue
Copy link

j2emanue commented Apr 4, 2018

@GuanacoDevs thank you for the feedback. can you show code how you are deleting an account based on anonymous_user_uid only ? i see to delete an account i call currentUser.delete(). i dont see how your getting the anonymous user by uid ? your not even logged in anymore as the anonymous user so how can the account be deleted ? although with the admin sdk i see a way: FirebaseAuth.getInstance().deleteUserAsync(uid).get();

@GuanacoDevs
Copy link

GuanacoDevs commented Apr 4, 2018

@j2emanue Hey man, I meant Google Cloud Functions, not within your App, using GCF you can delete any user even if is not signed In. Delete User.
Now what I do with those functions is to set different triggers, that will execute them in case:
New User Signs In or Returning User already has data.
My app always signs them Anonymously.
1- When they choose to sign in I backup their Anonymous data under a node which is Readable/Writable by everyone as long as they are Authenticated, I set a flag under that node that triggers a copyAnonymousUser GCF and I save in sharedPreferences() the anonymousUid before launching FirebaseUIAuth.
2- If for some reason they don't sign in I delete their backup in onActivityResult()
3- If the signs In is completed I check if is a returning user, if so I just delete the Anonymous User data and account(I should update in case that used the app while anonymous, but I'm waiting for the silent sign in @SUPERCILEX ), I use the anonymousUid saved before to trigger a function so that it will know what data and user to delete.
4- If is a new user I use the backed up data to populate its "new" account. After that I clean the "shared" node, for this I trigger another function to execute always from GCF
They just released v1.0
Note that I'm not linking accounts, just copy/paste/delete
Wish I knew how to do this before, now my database is cleaner.
I really suck at Java Script because functions is the only reason I have to use it, so virtually I'm not really sure what I'm doing.

Regards
GuanacoDevs

@SUPERCILEX
Copy link
Collaborator

@GuanacoDevs Silent sign-in is ready on my side, just waiting on @samtstern's approval. 🙃

@curiousily
Copy link

Hey @SUPERCILEX,

What (stable?) commit hash from your branch would you recommend that targets Play Services 15?

Thanks for your response. Our team already implemented your suggestions!

Cheers!

@SUPERCILEX
Copy link
Collaborator

@curiousily Sweet! I'd go with 38e2ece9bb—it includes 3.4-dev, but that's only db and opt-in auth features (e.g. #1212) + bug fixes so nothing to worry about.

@unxavi
Copy link

unxavi commented May 25, 2018

Hey @SUPERCILEX ,

Did this made it to the v4.0.0? If not what would be the last stable commit hash from your branch? Is it the same from Apr 25 38e2ece9bb ?

Thanks a lot!

@unxavi
Copy link

unxavi commented May 25, 2018

@GuanacoDevs and where do you merge the data from anonymous user with the new signed in user? We are talking about linking an anonymous account with a user account on the sign in process, no?

@samtstern
Copy link
Contributor

@unxavi @GuanacoDevs I think there is some confusion. The new "silent sign-in" feature is not related to this issue at all. Anonymous upgrade has not been shipped.

@GuanacoDevs
Copy link

@unxavi @samtstern Apologies, I read my previous post here and not the title of the issue, got confused.

@curiousily
Copy link

curiousily commented May 27, 2018

Hey @SUPERCILEX,

Any new recommended hash that includes the changes in 4.0? Would you recommend a way to select hashes by ourselves, so I don't bother you every now and then?

Not even #1185 made it into 4.0...

Sorry to bother you again. Thanks for the hard work you're putting in!

@SUPERCILEX
Copy link
Collaborator

@unxavi @curiousily no worries about asking for new hashes. 😊 (Though if you go to the Commits tab here, you'll find the latest and greatest.) Anyway, c280098444 includes 4.0 plus the account linking stuff. Cheers! 🥂

@ghost
Copy link

ghost commented Jun 6, 2018

how can I add Authenticate with Firebase Anonymously into FirebaseUI

like this

enter image description here
capture

Although the user can log in anonymously, I need to give the user a different id to identify the user

@SUPERCILEX
Copy link
Collaborator

@mike1128 The point is that it's anonymous. 😉 So basically, you just call FirebaseAuth#signInAnonymously() and you're good. There's no UI.

@ghost
Copy link

ghost commented Jun 6, 2018

I want them in the same page.

So user can choose sign in with facebook or email or sign in anonymously

from one interface.

@SUPERCILEX
Copy link
Collaborator

@mike1128 This isn't something the user interacts with though. Typically, you'd call signInAnonymously() on app start if the user isn't signed in.

@ghost
Copy link

ghost commented Jun 6, 2018

Thank you for your replying.

But it doesn't solve the problem.

If I call signInAnonymously(), I should give user a button.

so it's two interface or page, not one.

what i want it like this

startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.FacebookBuilder().build(),
new AuthUI.IdpConfig.AnonymousBuilder().build()))
.build(),
RC_SIGN_IN);

and then Handling the sign-in response

like
if (requestCode == RC_SIGN_IN)
{
if (resultCode == RESULT_OK)
{
//write uid to firestore

@SUPERCILEX
Copy link
Collaborator

I see what you're saying, but the whole point of signInAnonymously() is that there's no user interaction. So that means no button. You should call the method on app start without the user needing to do anything.

@ghost
Copy link

ghost commented Jun 6, 2018

what if user want to sign in on app start?
so I need give the user a choice to sign in with email or sign in with facebook,
or sign in anonymous

@SUPERCILEX
Copy link
Collaborator

Oh, I think I see where you're confused. Anonymous sign-in isn't persisted anywhere. That means if the user re-installs your app one way or another they'll lose all their data. The point of my fork is that you sign in anonymously on app start so you can use the db and all that, then when the user is ready to sign-in after going through tutorials or something, you present them with a reliable sign-in method.

@samtstern
Copy link
Contributor

Hi all,

Some basic support for this feature has been released in version 4.1.0. More to come!

@SUPERCILEX
Copy link
Collaborator

I'm going to attempt to clarify and organize what's going on so this post can be used as a starting point for any newcomers.

Current state of affairs

Public releases of FUI include support for non-conflicting upgrades. What does that mean? If a user only has an anonymous account and then signs up for a real account, you're good to go. However, anytime the user is signed in anonymously but already has a real account, you'll run into a merge conflict which can't be resolved nicely. BTW, when I say "real" account, I mean something with a stable ID like an email or phone.

What does the fork do?

Simply put, it lets you resolve merge conflicts by transferring a user's data to their real account with security rules in mind.

How do I get it?

Setup JitPack with this repo: com.github.SUPERCILEX.FirebaseUI-Android:firebase-ui-auth:60f451cfea

Documentation can be found here: https://github.com/SUPERCILEX/FirebaseUI-Android/blob/anonymous-auth/auth/README.md#account-linking

@hummatli
Copy link

hummatli commented May 6, 2020

Hi, folk. I found a method called enableAnonymousUsersAutoUpgrade(). It converts the anonymous user to a permanent one.

I don't know when it was added but I think it answers the question.

AuthUI.getInstance()
.createSignInIntentBuilder()
.enableAnonymousUsersAutoUpgrade()
.build()

@percula
Copy link

percula commented May 11, 2020

@SUPERCILEX , can you please comment on this enableAnonymousUsersAutoUpgrade()? Is it comparable to your fork? Thanks!

Edit: Just looked at the documentation. They appear to be similar. The key difference is "When linking is unsuccessful due to user collision, an error with code ErrorCodes.ANONYMOUS_UPGRADE_MERGE_CONFLICT will be returned to onActivityResult()". So instead of passing a merge conflict class, you handle it in onActivityResult()

@danijorda1
Copy link

Hi @SUPERCILEX could you please create a new build with firebase-ui-auth:8.0.0 ? Phone Auth is not working in higher versions of Android with firebase-ui-auth:4.2.0

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests