6

I have a use case where User A can say that User B borrowed from User A some amount of money, similar to apps like Splitwise.

I'm using firestore to store the data. In this particular case, I'll store it as a document in the "Transactions" collection which will have the following fields:

amount: 20
fromUser: uid for User A
toUser: uid for User B

The issue here is that the User B doesn't exist yet and so there is no uid for the user B. What I want to do is to create a temporary user for User B with the email address which will generate a uid. And later when the User B signs up on the app, the same user is upgraded to a permanent user with whatever auth provider the User B has used.

While searching, I came across - https://www.freecodecamp.org/news/heres-what-i-wish-i-knew-before-i-started-using-firebase-9110d393e193/

Which mentions that this was possible with the firebase invites which is now depreciated. So, is there any other way to achieve this behavior now?

Christopher Peisert
  • 21,862
  • 3
  • 86
  • 117
Akshay Jain
  • 884
  • 5
  • 19

2 Answers2

6

Firebase supports creating anonymous user accounts for just such scenarios.

Authenticate with Firebase Anonymously

You can use Firebase Authentication to create and use temporary anonymous accounts to authenticate with Firebase. These temporary anonymous accounts can be used to allow users who haven't yet signed up to your app to work with data protected by security rules. If an anonymous user decides to sign up to your app, you can link their sign-in credentials to the anonymous account so that they can continue to work with their protected data in future sessions.


Email Address of 2nd User Known

If you already have the email address for a user (User B) that has not yet signed up, then you can create their account using the Firebase Admin SDK.

See Create a user

The new User B email address could then be configured for Email Link Authentication by calling firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings).

Since the User B account creation was initiated by User A, you would not be able to use Local Storage to save the email of User B to complete sign-in with the email link. However, this is not a problem, since as the documentation example shows, you may prompt the user for their email address.

if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  email = window.prompt('Please provide your email for confirmation');
  
  // The client SDK will parse the code from the link for you.
  firebase.auth().signInWithEmailLink(email, window.location.href)

  ...

Now that User B has successfully signed in using the email link, the standard process may be followed to Link Multiple Auth Providers.

Community
  • 1
  • 1
Christopher Peisert
  • 21,862
  • 3
  • 86
  • 117
  • Anonymous authentication is useful when the user starts using the app and we allow a session without the user providing the details like an email address- This is not the case here. I have the user's email address but the user has not started using the app and has been invited by an existing user. Another solution with creating the user with admin SDK is having a different issue. If Say, I create a user with email when he was invited. When the user with that email address starts using the app, they will get an error while registering that the user already exists! – Akshay Jain Aug 27 '19 at 06:21
  • @AkshayJain See updated answer with an example scenario for signing in *User B* using email link auth, which then enables linking multiple auth providers. – Christopher Peisert Aug 27 '19 at 12:36
  • Okay. Looks doable. Do you have any way to do it on Android only? – Akshay Jain Aug 27 '19 at 12:51
  • @AkshayJain see [Authenticate with Firebase Using Email Link in Android](https://firebase.google.com/docs/auth/android/email-link-auth) – Christopher Peisert Aug 27 '19 at 12:57
  • 1
    @Christopher Peisert I was also thinking about creating a user with Admin SDK. However, it raises few problems for the user. Email link can expire in case user decides to join the app a day later, so the user will have to make another request. Another problem is if the user tries to sign up for the app, it will fail since the user already exists. Although these problems can be solved somehow, I wonder if there is a more convenient way to do it without confusing the invited user. – Can Aug 28 '19 at 07:17
  • Handling expired email links via error code `auth/expired-action-code` as well as errors if the account already exists are not perfect. But it avoids security risks, such as creating temporary passwords. Typically the Admin SDK would be used to import users from another auth system where you already have passwords or social provider info. Otherwise, the better option is to have users sign up for accounts without creating them in advance (standard use case). – Christopher Peisert Aug 28 '19 at 12:38
  • This is also what I am thinking. Although firebase invites were exactly for this purpose but they decided to depreciate them. I think I will go for the approach of using email address till the user is created as email address is the only identity for the invited user. On creating the user, I will replace the email address with the user ids everywhere. For the case with email authentication, it will not work because as Can said it will give an error that the user already exists. The invited user might register after months and that too without using the invite at all. – Akshay Jain Aug 28 '19 at 13:59
1

The server side (aka Node.js) Admin SDK allows you to create users programatically. You would need some way to pin/stick the newly created user UID to userB. Email address would seem the easiest way. So UserA would need to specify the email address of userB, then you process that server side Admin SDK.

When user B signs in with their email address, Firebase Authentication will detect an existing account with userB's email address and throw an error which you can use to merge userB's account data.

Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • Merging is the major part here I am not able to figure out. There is no trigger for cloud functions on a failed sign up. The trigger is there only when a new user is created. In this case, the user will get an error that the user already exists, but what after that? Especially the cases when the user wants to register using the social identity providers? – Akshay Jain Aug 27 '19 at 06:23
  • @AkshayJain I got it setup but it wasn't easy. The key is to setup realtime listeners. ...and you're right, you `case`/`switch` or `if` the error to handle the specific error/reason the merge failed. If user w email already exists vs other specific error codes. it's manual handle. it can be done. i did it. – Ronnie Royston Sep 06 '19 at 21:17