When using Firebase Authentication service, how to throw error when login by Facebook/Google with no existing account - firebase

I'm developing a Flutter app using Firebase Authentication service.
The following Flutter plugins are used:
Firebase_auth
Google_sign_in
Facebook_login
The login flow is:
Login with either Facebook, Google or Email&Password
If account has already been created, logged in
If not, throws error
This is possible if the logging method is Email&Password. In Firebase_auth plugin, there are two separate methods for Email&Password scenario: createUserWithEmailAndPassword and signInWithEmailAndPassword. When the sign in method is called with a non existed account, it will throw a wrong id/password error.
However, for the Facebook/Google login method, the plugin only provides
signInWithFacebook and signInWithGoogle and the way they work is that the first time user uses facebook/google account to sign in, Firebase will automatically create an account and return the newly created account. (no separate sign up and sign in process)
I also read on the Firebase doc for Android Google Sign in
After a user signs in for the first time, a new user account is created and linked to the credentials—that is, the user name and password, phone number, or auth provider information—the user signed in with. This new account is stored as part of your Firebase project, and can be used to identify a user across every app in your project, regardless of how the user signs in.
So, my question is: If user logins with Fb/G account that has not yet been used to register with my app on Firebase, how do I make Firebase authentication throw error instead of automatically create a new account ?

Malcolm from the Firebase team here! Great question.
Given the functionality that currently exists in the open source Flutter plugins, you can likely get the result you desire by using the method #fetchProvidersForEmail(). Here are the logical steps you'll follow for the federated IDPs:
Do normal sign in the with IDP and get a token.
Parse that returned token for the user's email (usually using a JWT parsing library).
Call #fetchProvidersForEmail() with the extracted email.
If the providers that come back for the email are empty, then it's a new account. Otherwise, it's an existing account.
Alternatively, you could update the Flutter plugin to return more of the AuthResult, which includes whether or not the user is new. If the user is new, then you just call FirebaseAuth#getCurrentUser()#delete() and throw whatever error you wanted. (Which you would also have to add to the plugin).

Related

Is there a way to log out a specific user using firebase auth go sdk?

background of this question
I'm using firebase auth for user authentication on my app.
I realized that firebase doesn't have a log of user information changes, so I can't answer user questions about it.
So, I'm planning to move the feature of changing user account info (like email, display name, and password) from using the client-side firebase auth library to using server-side firebase auth SDK for the purpose of taking logs of these changes to use for user support. Also, I'd like to make logout a user who changes account info.
I've looked for the appropriate API on the document firebase.google.com/go/v4/auth and found UpdateUser function. The struct UserToUpdate which is a parameter of UpdateUser can set a new email address, new password and new display name, but I can't find to set the parameter to make a user logout.
my question
Is there a way to log out a specific user by firebase auth go SDK?
Firebase Authentication's client-side sign-in is based on ID tokens, which are valid until their built-in expiration (by default: an hour after they are minted). Since no server keeps a list of all the ID tokens it has minted, there is no way to mark a token as invalid on such a list either.
The common approach to revoke access for a user is to:
Revoke the refresh token, so that they can no longer mint new ID tokens with it.
Add the ID token(s) of the user to a self-managed list of revoked ID tokens.
Detect the presence of an ID token in this list from your server-side code and security rules.
Optionally detect the refresh token revocation on the client
Instead of logging the user out, you can also force-refresh their ID token/profile on the client to get the latest information from the server.

How to make firebase not create a new user for Google OAuth on sign in?

On sign in using firebase's Google OAuth provider, it automatically creates an account for the user if one does not exist. Is there a way to not create an account and return an error on sign in?
(https://firebase.google.com/docs/auth/web/google-signin)
When you call the sign-in method, it will create an account for the user if it does not exist.
If you want to check if an account exists or not, you would have to perform the "Login with Google" OAuth flow yourself (without the Firebase SDK) and then use a Cloud function to check if a user with the email exists (you might also have to maintain a list of users (their emails) in Firestore). If not, then you can create a new account with the access token you received.

Flutter Firebase authentication - new anonymous user generated following sign-out and sign-in

The Firebase Authentication documentation states that:
If no previous anonymous account on the platform (for your specific application) has been created, when signing in anonymously Firebase will create a new unique user which will be persisted across app restarts/page reloads. If the user signs-out and reauthenticates anonymously again, they will be signed-in with the previously created account.
Yet when I sign out as an anonymous user and sign in again, I get a new anonymous user, instead of getting signed in with the previously created account. Just to be clear, the sign-in is done by calling FirebaseAuth.instance.signInAnonymously(), and the sign-out is done by calling FirebaseAuth.instance.signOut().
That looks like a mistake in the FlutterFire documentation. Once you sign out from an anonymous account, that account's UID is lost and cannot be reclaimed.
My best guess at the intention of the documentation is that calling signInAnonymously multiple times will result in the same UID. But signing the user out, clears that UID and it can't be reclaimed. I submitted a PR to improve the documentation here.

Firebase: Link facebook account with existing user

I have a current database with active users in Firebase that can login with user/pwd but now I'm implementing the facebook login and I realised the only way to link a facebook account with an existing user is only when the user is already logged with the user/pwd but not before the login.
I have two buttons in my app (login with fb and with email) but if I try to login with fb using the same email of an existing user, I will receive the following error auth/account-exists-with-different-credential and the documentation says that in order to fix this the user needs to login first then link.
Do you know if there is a way to link both accounts but without perform a login first, I mean, from the login view?
You need to sign in the user first before linking. This is important if you want to ensure it is the same user. Otherwise you can switch to multiple accounts per email in the Firebase console.
The way to solve this, when you get the error auth/account-exists-with-different-credential, the error will contain error.email and error.credential after you sign in with Facebook and the account already exists as a password account.
You then call firebase.auth().fetchProvidersForEmail(error.email) to which resolves with the list of provider IDs for that email. In this case, it will contain ['password']. You then ask the user to provide their password. You call signInWithEmailAndPassword(error.email, password) to sign-in the original user. You then call firebase.auth().currentUser.linkWithCredential(error.credential) to link the Facebook credential to the password account. Now both accounts are merged and the user can sign in with either.
I fixed it by going to the Firebase console. then head over to the authentication section and select the Settings Tab. Afterwards, go to User account linking and check Create multiple accounts for each identity provider

Firebase creating empty users, even though the Auth feature requires email

I am using Firebase's auth feature and sometimes I see empty users in the console. This brings issues to some users because instead of logging into their main account (and using their UID to fetch their user data in a users reference), log into that empty account with a UID which is not theirs.
Not sure exactly how that can happen, but it seems like this could be a bug on Firebase's side, because a successful Auth should have at least 1 provider...
Any ideas about such issue and how I could fix it from my side if possible?
Ps.: Is that how "signInAnonymously" would create anonymous accounts?
This is an intended behavior when you authenticate with Firebase anonymously.
signInAnonymously() method signs in the user anonymously without requiring any credential and creates a new account in your Firebase Authentication system, except in the case where there was already an anonymous user signed in into the app.
See FirebaseAuth.signInAnonymously class reference for more details.

Resources