How to check if an email exists in Firebase Authentication? - java

I am trying to check if an email already exists in Firebase authentication, but I can find something for Java.
I am trying to do something like searching in a list of emails and if that email is not in the database (emailNotExistsInDatabase(email)), then continue.

In addition to the very complete response from Alex, another possible approach is to use a Callable Cloud Function that you call from your app.
Since we use the Admin SDK in Cloud Functions you can use the getUserByEmail() method.
The function would look like:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.checkEmailExists = functions.https.onCall((data, context) => {
return admin.auth()
.getUserByEmail(data.email)
.then((userRecord) => {
return { emailExists: true }
})
.catch((error) => {
throw new functions.https.HttpsError('invalid-argument', "email doesn't exist");
});
});
With this approach you don't need a specific Firestore collection. The Admin SDK will directly query the Auth service.
Look at the doc for instructions on how to call the Callable Cloud Function from your app.
Note that the above approach is valid if you want to check if a user exists from an application (e.g. an Android app).
If you already use the Admin SDK from a Java based server, you just have to use the getUserByEmail() method in your server code.

There is no method inside the FirebaseAuth class that can help you check the existence of a user based on an email address. If you need that functionality you have to create it yourself. This means that when a user signs in for the first time into your app, then save user data in Firestore using a schema that looks like this:
db
|
--- users (collection)
|
--- $uid (document)
|
--- email: "user-email#gmail.com"
To check if a user with the user-email#gmail.com already exists, then you have to perform a query that looks like this in Java:
FirebaseFirestore db = FirebaseFirestore.getInstance();
Query queryByEmail = db.collection("users").whereEqualTo("email", "user-email#gmail.com");
queryByEmail.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document.exists()) {
Log.d(TAG, "User already exists.");
} else {
Log.d(TAG, "User doesn't exist.");
}
}
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Another solution would be to use Query#count() method:
queryByEmail.count();
If the result is > 0 then it means that the user already exists, otherwise it doesn't exist.

If you want to check if a given email address is associated with a user profile in Firebase, you can call the fetchSignInMethodsForEmail API.
Note that this API gives malicious users a way to perform a so-called enumeration attack, so you can actually nowadays disable fetchSignInMethodsForEmail - in which case calling it from your app would fail.
Also see:
Check if given email exists
Check if an email already exists in Firebase Auth in Flutter App

Related

Android Cloud Firestore task's return successfully when there is no internet connection. How?

I'm messing around with Cloud Firestore.
I would like to simply get a callback when reading from DB fails, so I can show a dialog to the user about he has no internet connection. Of course, this would need sophisticated exception handling, but first things first, I would like to just simply get a callback when the app cannot reach the server.
HOWEVER, whenever I test my application with an emulator which has no internet connection, I still get successful callbacks.
This is the log:
Logging_: onSuccess
Logging_: onComplete
Logging_: Task was successful without an internet connection, how?
How is it possible? Am I thinking right that Cloud Firestore is simply not available for this use case since it was built to provide cached data and aggressive syncing in order to provide a seamless user experience even when there is no internet connection?
I would just need a way to just KNOW whether the DB is reachable. (a.k.a - Is there an internet connection problem?)
Code is really simple, it just tries to reach for the current account's characters.
db.collection("users")
.document(accountId)
.collection("characters")
.get()
.addOnCanceledListener(new OnCanceledListener() {
#Override
public void onCanceled() {
Log.i("Logging_", "onCanceled");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i("Logging_", "onFailure");
}
})
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
Log.i("Logging_", "onSuccess");
}
})
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
Log.i("Logging_", "onComplete");
if (task.isSuccessful()) {
Log.i("Logging_", "Task was successful without internet connection, how?");
} else {
Log.i("Logging_", "Task wasn't successful.");
}
}
});
I would like to simply get a callback when reading from DB fails, so I can show a dialog to the user about whether he has no internet connection.
The Firestore SDK doesn't throw an error when there is no internet connection, and it makes sense since Firestore is designed to work offline. Behind the scenes, Firestore SDK tries to reconnect until the devices regain connectivity. So not having an internet connection cannot be considered a failure. If you want to check for internet connectivity, the following answer might help:
How to verify if user has network access and show a pop-up alert when there isn't
Please notice that Firestore has a built-in mechanism that can help know when an error occurs. So the failure callback occurs when Firestore servers reject the request due to a security rule issue.
There is a solution in which you can force the retrieval of data only from the cache or from the server. Here is the official documentation regarding source options:
https://firebase.google.com/docs/firestore/query-data/get-data#source_options
Firestore has built in caching that is enabled by default for reading from a database on Apple and Android devices. If you want to disable being able to read the cached data, you can do something like this:
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(false)
.build();
db.setFirestoreSettings(settings);
I think what you may want to do instead is listen to network events in Android which would allow you to update the user if they try to perform an action while there is no network available.
This might be a bug. I have logged the tracking info here on GitHub

How to check Google Play Protect status?

I'm creating an anti-virus software, and I would like to know if Google Play Protect is enabled or disabled? I'm using Java in Android Studio. Are there any permissions required to access this information?
You can check if Google Play Protect (also known as Verify Apps) is enabled using the SafetyNet Verify Apps API (see that link for more details, including a Kotlin version and an option to prompt the user to enable it if it's disabled).
It's an asynchronous API, so you'll have to write a callback, something like:
SafetyNet.getClient(context)
.isVerifyAppsEnabled()
.addOnCompleteListener(new OnCompleteListener<VerifyAppsUserResponse>() {
#Override
public void onComplete(Task<VerifyAppsUserResponse> task) {
if (task.isSuccessful()) {
VerifyAppsUserResponse result = task.getResult();
if (result.isVerifyAppsEnabled()) {
// It's enabled, handle that case here
} else {
// It's not enabled, handle that case here
}
} else {
// An error occurred, we don't know whether it's enabled
}
}
});
The context parameter would just be your this if you're calling it from an Activity or Service.

Hi can I show user status when he or she is online or vice-versia using firebase in android?

How can I show user status when he or she is online or vice-versa using firebase? Can you give me sample project or app example where it was implemented in android?
A simple way in which you can achieve this, is to create a new node in your Firebase database to hold all online users, so when the user opens the application, you'll immediately add his id to this new created node. Then, if you want to check if the user is online, just check if his particular id exist beneath that node.
Another approach would be to add a new property named isOnline for each user in your database and then use it accordingly. For this, I recommend you to use Firebase's built-in onDisconnect() method. It enables you to predefine an operation that will happen as soon as the client becomes disconnected.
See Firebase documentation for presence.
You can also detecting the connection state of the user. For many presence-related features, it is useful for your app to know when it is online or offline. Firebase Realtime Database provides a special location at:
/.info/connected`
Which is updated every time the Firebase realtime Database client's connection state changes. Here is an example also from the official documentation:
DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("connected");
} else {
System.out.println("not connected");
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});

Get User Email From Uid Without Login to app Firebase

I have created a Firebase app.
Is there any way to get user email by Uid Without login to the app?
No the user has to be logged in to be able to retrieve his information based on the userid
To get the uid, you need to do this:
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
String userid=user.getUid();
According to the docs:
public FirebaseUser getCurrentUser ()
Returns the currently signed-in FirebaseUser or null if there is none.
more info here:
https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuth.html#getCurrentUser()
Of course it is possible, you can use Firebase Cloud Functions. You can write a cloud function which will return user mail by UID param :) No firebase authentication required, simple and awesome. Here is a short example:
const admin = require('firebase-admin');
exports.getUserMail = functions.https.onRequest((req, resp) => {
admin.auth().getUser(req.query.uid)
}
It is not possible without logging in. Your email address and password are stored separately from the user data for security reasons. See below:
How do I return a list of users if I use the Firebase simple username & password authentication
Use the Firebase Admin SDK. You can lookup a user by uid, email or phone number:
https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data
admin.auth().getUser(uid)
.then(function(userRecord) {
console.log(userRecord.email);
})
.catch(function(error) {
console.log("Error fetching user data:", error);
});

Create user with Auth and write to Firestore at the same time

I have a scenario where I need to create a user using the Auth and add more info (such as name and type of business) to Firestore database. Firestore as transaction/batch operation but it is for Firestore only.
Is there a way where I can perform Auth operation such as create along with the Firestore data insert. Both operation has to succeed or fail. Right now I chain them but I would be worried that one fails and the other success in which a will need to handle gracefully.
Thank you
When you are implementing Firebase authentication you can use a addOnCompleteListener or addOnSuccessListener and implement either the isComplete() or isSuccessful() methods. Inside one of these methods you need to create the user in your Firestore database. With other words, you will create the user only if the authentication is successful. So if isSuccessful() either all of the operations beneath one of that methods succeed, or none of them are applied.
The difference between those 2 methods is that we can that a Task is complete when the work represented by that Task is finished, regardless of its success or failure. There may be or may be not an error but we need to check for that. A Task is successful when the work represented by the task is finished, as expected, with no errors.
As o conclusion, there is no way to have a bulk solution. This is because there are 2 separate operations. So in order to be able to write user details in the database you need to be first successfully authenticated. If you want a rollback then you need to use again an addOnCompleteListener when you write user details to the database. If the you get an error just sin-out the user. There is no transaction/batch operation that can handle authentication and a database write operation as you described.
Edit:
Since you say you are using Firebase authentication, you can also use a function, written in Cloud Function to reach your goal. You can write a function that will run every time something in your project happens. One of those "things", is the creation of an user. With other words, you can execute your logic every time a new user is created. Here's an example:
exports.updateUserCount = functions.auth.user().onCreate((user) => {
//Do what you need to do
});
Also, you can do the same thing on a user deletion, but registering a function using onDelete() method.
This will be very fast because there is no interaction with user's device. Please see more information about Firebase Cloud Functions.
The best way to do scenarios like this is to use Firebase Cloud Functions. Cloud functions are triggered on various create/update/delete/write operations. You can trigger a cloud function on new user creation and then do the related Auth creation inside it.
https://firebase.google.com/docs/firestore/extend-with-functions
So in this case, you create user data first and in its success, call the Firebase Auth user creation. If you are worried about failure scenarios, you can remove the created user if in case the auth creation fails.
I have solved this problem by using cloud function to create both auth user and firestore document. This way you can easily have some additional data required to create your user like invite code or things like that.
export const signUp = functions.https.onCall(async (data, context) => {
const email = data.email;
const password = data.password;
const firstName = data.firstName;
const lastName = data.lastName;
const inviteCode = data.inviteCode;
const userRecord = await admin.auth().createUser({
email: email,
displayName: (firstName && lastName) ? (firstName + ' ' + lastName) : (firstName ?? lastName),
password: password
});
await admin.firestore().collection(constants.COLL_USERS).doc(userRecord.uid).set({
inviteCode: inviteCode
})
});
If on the same time you want to do authentication and also want to save other details in the FireStore, then you can also do in this way.
if let email = emailTextfield.text ,let password = passwordTextfield.text, let sendername = nameTextField.text {
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.showAlert(e.localizedDescription)
}
else{
self.db.collection(K.FStore.registeredDetails).addDocument(data: [K.FStore.registeredName : sendername,
K.FStore.registeredEmail : self.emailTextfield.text!
])
self.performSegue(withIdentifier: K.registerSegue, sender: self)
}
}
}

Categories