I want to delete user from firebase authentication and also want to delete data from real-time database if the user doesn't verify email address with in 1 hours. Deleting a user is easy but if doesn't verify in 1 hour then how could I do this? The problem is that firebase is server less.
Write and deploy a scheduled function that periodically:
Queries your database for users who have not verified (you will need a child to record that).
Delete the database record and also delete the user account.
You will need to use the Firebase Admin SDK for both of these steps.
It's so easy! just create a real-time database of the unverified user database. and when the user signup the time will be also registered in the database. So when the apps start it check the unverified users and there you write the if-else statement if the difference between time is greater than 1hour the user will be deleted.
It's so simple as I said :)
Run firebaseAuth.getCurrentUser().isEmailVerified() function inside signInWithEmailAndPassword function to see if user is verified or not. if user is verfied then only create users database otherwise give an exception and break the function, it won't save unverified users data.
firebaseAuth.signInWithEmailAndPassword(Email,Pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
if (firebaseAuth.getCurrentUser().isEmailVerified()){
FirebaseUser user = firebaseAuth.getCurrentUser();
Uid = user.getUid();
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (!snapshot.hasChild(Uid)){
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child(Uid);
HashMap<String,String> userMap = new HashMap<>();
userMap.put("Name","default");
userMap.put("email",Email);
databaseReference.setValue(userMap).addOnCompleteListener(new OnCompleteListener<Void>() {
//call your function here when user sign in first time after email verification
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
//call your function when user already registered and verified
//and already saved his information to database
}else{
//show your exception here
}
}else{
//show your exception here
}
}
});
Related
I am a newbie in Firebase. Recently I am trying to save users into Firebase but I can't. When I generate the APK and run it onto the real device(Not Emulator), the new user does not add it into the Firebase. Also, no errors shown up. Task executed properly and go to OTPActivity. Here is my complete code:
public void saveUser()
{
firebaseAuth.createUserWithEmailAndPassword(emailAddress.getText().toString(),password.getText().toString()).addOnCompleteListener(ChatUserSignUpActivity.this,new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful())
{
FirebaseUser user = firebaseAuth.getCurrentUser();
Intent intent = new Intent(ChatUserSignUpActivity.this, OTPActivity.class);
intent.putExtra("phoneNum",emailAddress.getText().toString());
startActivity(intent);
}
else
{
Toast.makeText(ChatUserSignUpActivity.this, task.getException().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
Please help me. Thanks in advance.
When you authenticate your users with email and password, no data is saved into Firestore, nor in the Realtime Database. If you need to save the database in the database, you need to write code for that. So once your user is authenticated, you can get the data from the FirebaseUser object and write it to the database of your choice.
I'm using Firebase Authentication in my app (email and password auth).
In the onStart() method of my Login activity I retrieve the current user using:
FirebaseUser currentUser = mAuth.getCurrentUser();
The problem comes when the user is deleted from the database, the mAuth.getCurrentUser() method still retrieves the user and allows authentication.
How can I check if the user still exists?
Thx!
Try using something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child("email").addListenerForSingleValueEvent(new
ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
// used "email" already exists and is not deleted
} else {
// User does not exist. Add here your logic if the user doesn't exist
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Or check some of the following SO questions and answers:
Firebase authentication for checking if the user exists in the database or not
Firebase Auth - with Email and Password - Check user already registered
You can use getInstance. This worked for me fine. You don't get an instance with it.
private boolean isSignedIn() {
return FirebaseAuth.getInstance().getCurrentUser() != null;
}
Delete the userdata and make the currentuser null:
Follow the below code.
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User account deleted.");
//Remove the information f the user from database.
}
}
});
The code below works great on android to confirm if the Firebase Auth user still exists (has not been deleted or disabled) and has valid credentials.
Deleting the Auth user from the firebase console does not revoke auth tokens on devices the user is currently logged in as the token is cached locally. Using reload() forces a check with the firebase auth server.
currentUser.reload().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
//User still exists and credentials are valid
}else {
//User has been disabled, deleted or login credentials are no longer valid,
//so send them to Login screen
}
}
});
This question already has answers here:
How can I detect if user first time in Firebase [duplicate]
(4 answers)
Closed 4 years ago.
I have used the firebase authentication with phone number in my android app. But firebase doesn't give different functions for sign in and sign up like the email password authentication. How can I check if the user already exists?
What you can do in this case is that, store the phone number of every signed up user in the phone node of your Firebase database.
Then when signing a new user from a phone number, you can run a check in your phone node, that wether the phone number exists or not.
To store the phone number in a node named phone in your database, you can use a code like this:
private void signInWithPhoneAuthCredential(PhoneAuthCredential credential){
mAuth.signInWithCredential(credential).addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
// you may be using a signIn with phone number like this, now here you can save the phone number in your database
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("phone");
ref.child(phoneNumber).setValue(phoneNumber);
}
else if(task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
Toast.makeText(MainActivity.this, "OTP is incorrect", Toast.LENGTH_SHORT).show();
}
}
});
}
In the above code, phoneNumber is the number of the user you're signing up. Also I have used the heading name and value same, and that is, phoneNumber itself. You can use a name or anything else, you want.
Now when you're signing up a new user, you should run a check in your phone node in your database, using the following piece of code. You can add instance to this new method in the code above.
boolean checkForPhoneNumber(String number){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.orderByChild("phone").equalTo(number).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
return true;
else
return false;
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
I'm trying to create an app on Android that stores user contact info.
When the user creates a "contact card" to send to another user, I'd like it to display things I stored when registering the user, name, year, number etc.
When I push, firebase creates a unique key, and when I create a FirebaseUser it creates a uid. for ease, I save the uid as part of the user structure.
I'm now attempting to access that user using the uid, unfortunately the uid is not the key.
So, I'm trying to query.
I create a Firebaseuser
currentUser = firebaseAuth.getCurrentUser.getUid.
then I try to query by
DatabaseReference ref = firebase.getinstance().getReference("user);
ref.orderByChild("Uid").equalto(currentUser.getUid());
Is this correct? after I try to add a single valuelistener to obtain the actual values inside this user. Unfortunately this crashes. Can someone point me in the right direction?
You can use the user uid as the key to save the user info like this:
private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();
User user = new User(name, email);
mDatabase.child("users").child(userUid).setValue(user);
Then you can get the user info like this
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get User object and use the values to update the UI
User user= dataSnapshot.getValue(User.class);
// ...
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting User failed, log a message
Log.w(TAG, "loadUser:onCancelled", databaseError.toException());
// ...
}
};
mDatabase.child("users").child(userUid).addValueEventListener(userListener);
If this doesn't work, write the error log on the OP please ;)
Users are created using Email and Password. This is how I do the Sign-up:
mSignup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mUsernameStr = mUsername.getText().toString();
mIsSgl = mSglCheckBox.isChecked();
mUsernameStr=mUsername.getText().toString();
final User mUser = new User();
mUser.setEmail(mEmailStr);
mUser.setPassword(mPasswordStr);
mUser.setIsSgl(mIsSgl);
mUser.setStudyGroupName(mStudyGroupName);
mUser.setUsername(mUsernameStr);
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
generateUser(mUser);
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
This is how I push the data into database:
public void generateUser(User user)
{
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference users;
if(user.getIsSgl())
{
users = database.getReference(user.getStudyGroupName()).child("SGL");
}
else
{
users = database.getReference(user.getStudyGroupName()).child("Student");
}
users.push().setValue(user);
}
This is how I Sign-in:
mSignin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText().toString());
mPasswordStr = mPassword.getText().toString();
mAuth.signInWithEmailAndPassword(mEmailStr, mPasswordStr).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()){
FirebaseDatabase database = FirebaseDatabase.getInstance();
// thats not worked for me
database.getReference("StudyGroups").child("Student").orderByChild("email").equalTo(mEmailStr).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
userKey = childSnapShot.getKey();
}
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Toast.makeText(getActivity(), "Sucsses ", Toast.LENGTH_SHORT).show();
startActivity (new Intent(getActivity(),Controller.class));
}else {
Toast.makeText(getActivity(), "not sucsses", Toast.LENGTH_SHORT).show();
}
}
});
}
});
I want to query the database so that when a user signs-in by Email and password, it returns all the data of that user from the database.
How can I make the key of userId in Auth equal to the userId in database and how do I use that feature?
tl;dr - In this case, store each user using their associated uid generated by Fireabase Auth instead of using a push ID.
In your situation the challenge with using a push ID to store info specific to each user is that when a user signs in you don't know the push ID you used when you first stored their info. To find a user each time they sign in you would have to search through every user in your database until you find a matching email/password to retrieve their correct profile information - the more users you have, the longer it would take to do the search. One alternative, which would probably be faster, is to use Firebase Authentication to create users and the Firebase Database to store any user specific information.
When you create a new user using Firebase Authentication it will assign a unique user id to the user that will be the same throughout the lifetime of the user. You then use the unique user id generated by Firebase Auth instead of a push ID to store user info in the database. The next time a user signs in you get the user's uid from Firebase Auth and use it to query the database to get that user's information.
Check the guide for how to create a password-based user and how to sign a user in using Firebase Auth: Create a password-based account
In order to use the unique uid generated by Firebase Auth I suggest a few changes to your code.
Update database structure
I suggest you update your database structure by adding a new location (maybe "allUsers") for use when you create/sign in users. Right now it looks like your are breaking up students into groups. If you need to keep this structure, for reasons beyond authentication, you can use it along with my suggestion. The reason for a single location which stores all users is that you need a definite location to query when a user signs in. When using Firebase Auth, without a single location which stores all users there is no way to tell what group a user belongs to when they first sign in. You would have to check every group in order to find a match and that may take a long time. Having a location which stores all users solves that problem. Also, the query for retrieving user information from that single location is much simpler. If you do need to keep a user's information in multiple places just be sure to update their information in both places if any changes occur.
Create a class variable used to distinguish between create user and sign in existing user.
If you use the same Activity to create a new user and sign in an existing user then create a boolean variable to make a distinction between when a new user is being created and when an existing user is signing in. It will be used later in the AuthStateListener. If you handle user creation in a separate activity from general sign in then you shouldn't need this variable because each activity would have a separate AuthStateListener.
boolean mIsNewUser = false;
Move the call to generateUser() from the create user completion listener to an AuthStateListener. Also move your database query from the sign in completion listener to the AuthStateLisener
Whenever you create a user successfully they will automatically be signed in too. So, if you move your call to generateUser() from the createUserWithEmailAndPassword OnCompleteListener to your AuthStateListener you can get access to the created user's uid. When signing an existing user move your database query to the AuthStateListener as well, again so we can access the user's uid. I'm also going to create a helper method for the database query called getExistingUserInfo. As an FYI, the onComplete() callback in the OnCompleteListeners for creating and signing in users gives you access to an AuthResult which according to the API has a method for returning the current user but the documentation says to access user information in the AuthStateListener.
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
if(mIsNewUser){
//call to generate user using Uid instead of pushID
generateUser(mUser, user.getUid());
} else{
getExistingUserInfo(user.getUid());
}
startActivity(new Intent(getActivity(), MainActivity.class));
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
// ...
}
}
#Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
Update your generateUser() helper method to use the uid instead of a push ID:
I'm going to assume you want to keep you existing database structure and add the single location for all users as suggested. Based on this I've made a couple of changes to the write operation you were using in generateUser(). Mainly, instead of using setValue() to write to the database I'm using updateChildren(). By using updateChildren() we can take advantage of Firebase's ability to do atomic updates. This will allow us to write to the appropriate student group location and the location storing all users simultaneously. By taking this approach if the write operation to either location fails neither location will be updated. This way you can be certain if a student is added to a group they will also be listed in the allUsers location.
private void generateUser(User user, String uid)
{
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
String userType;
String allusers = "allUsers/" + uid;
Map<String, Object> newUserUpdate = new HashMap<>();
if (user.getUsername() != null) {
if (user.isSgl()) {
userType = user.getStudyGroupName() + "/" + "SGL" + "/" + uid;
} else {
userType = user.getStudyGroupName() + "/" + "Student" + "/" + uid;
}
newUserUpdate.put(userType, user.serialize());
newUserUpdate.put(allusers, user.serialize());
database.updateChildren(newUserUpdate);
}
}
Update database query to use new location which stores all users
As I mentioned above, by creating a single location for all users you can reduce the complexity of the query used to find a user's info when they sign in. Again, if you need to store users by group you can keep that but be sure to update both locations if a users info changes.
public void getExistingUserInfo(String uid){
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference("allUsers").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//get user data from dataSnapshot
Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
Log.v("himaAbousalem",userKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Set the variable used to distinguish between existing user sign in and new user creation in the create user completion listener
FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(Task<AuthResult> task) {
if (task.isSuccessful()) {
//set boolean used in the AuthListener
mIsNewUser = true;
Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
}
}
});