I have integrated firebase as a backend in my android app.I am trying to change users device id every time app opens.
I am using below code to get firebase registration id:
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed", task.getException());
return;
}
// Get Instance ID token
String token = task.getResult().getToken();
Toast.makeText(MainActivity.this, token, Toast.LENGTH_SHORT).show();
}
});
How can I change this token every time users open an app.
Any help would be appreciated.
THANKS
The registration token may change when:
The app deletes Instance ID
The app is restored on a new device
The user uninstalls/reinstall the app
The user clears app data.
Read the documentation here
You can revoke the token from server and notify the device.
The procedure is well explained here.
Related
I'm starting a new project and Firebase Auth was the choice for authentication. The idea is to create/login users through Firebase Auth and then, use the Firebase ID Token to authenticate on my backend (through Authentication header).
In Google Samples, this is the way I should get the token:
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
But, as you can see, this is a async call, because it goes to Firebase servers to get me the Token. So, every REST API call to my backend, I need to run the above code, because I don't know when the token has expired.
Is there a better way to safety call my backend REST APIs using Firebase Auth? Or using the Firebase ID Token is the best one? If so, how should I wrap this id token get for every REST API call?
If you have a better way to authenticate users to call rest apis later, I'm all ears.
so the Idea is quite simple. You can use this method in the Android device as you already know:
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// Send token to your backend via HTTPS
// ...
} else {
// Handle error -> task.getException();
}
}
});
Once you hold the instance of the token you send it to your backend for authentication there, it will authenticate only once and send you backend a token that is managed by the backend itself. That's the token that will be sent in each subsequent call to the backend, not the generated by the above method.
I'm creating an Android application that will deliver notifications.
Users can opt-in with a phone number or an email account.
I just need to verify the email the user entered, I don't want to create a Firebase account
Firebase has a FirebaseUser#sendEmailVerification() but that will require to create an account.
In other words, I just want the email verification to be the same as the Phone verification, where Firebase will just send you a code or verification link.
Is there a way to leverage Firebase email verification without creating an account?
For anyone trying to accomplish the same, here's how I was able to do it.
Go to Fibrebase console and enable Email/Password and Anonymous sign-in methods on the Authentication screen
Firebase Authentication screen
Then in you code, create an Anonymous user (this is what does the trick, because now you have a valid user to verify against), change the email, and then send a verification. After that, reload the Firebase user and check isEmailVerified()
mAuth = FirebaseAuth.getInstance();
mAuth.signInAnonymously()
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "signInAnonymously:success");
if (mAuth.getCurrentUser().isEmailVerified() == false) {
mAuth.getCurrentUser().updateEmail("<MAIL YOU WANTO TO VERIFY HERE>");
mAuth.getCurrentUser().sendEmailVerification();
Log.e(TAG, "mail sent.....................................");
}
//updateUI(user);
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInAnonymously:failure", task.getException());
Toast.makeText(getApplicationContext(), "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
Here's the reloading part:
mAuth.getCurrentUser().reload()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.e(TAG,( mAuth.getCurrentUser().isEmailVerified() ? "VERIFIED" : "Not verified"));
}
});
Both phone number verification and email verification are tied to a Firebase Authentication account. There is no way to use them with such an account, since the result of a verification is that a the relevant property (email_verified or phone_number) in the user account gets updated.
So, I have enabled email/password in the dev console and everything is working fine. Except that I should be getting a confirmation email to the email I inputted, but I'm not getting it. I thought it does it automatically, but apparently it doesn't.
Method for signup:
public void signUp(View v) {
String email = emailET.getText().toString();
String password = passwordET.getText().toString();
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d("AD", "createUserWithEmail: " + task.isSuccessful() + task.getException());
if (!task.isSuccessful()) {
createDialogSignUpError(
getApplicationContext().getResources().getString(R.string.signUpFailedET),
getApplicationContext().getResources().getString(R.string.signUpFailedEM),
getApplicationContext().getResources().getString(android.R.string.ok));
Toast.makeText(SignUp.this, task.getException().toString(), Toast.LENGTH_LONG).show();
} else if (task.isSuccessful()) {
Toast.makeText(SignUp.this, "Registration Successful.", Toast.LENGTH_SHORT).show();
}
}
});
}
It should be sending, but sadly it's not. I've read somewhere on SO that you need to add a method or something to send the email, and it's missing in the docs, but that wasn't Java.
Edit
According to here, it is only supported in iOS and web. Which is pretty surprising, since after all, android IS Google, and Google is Firebase. So is it possible even with creating a custom sent email?
Edit 2: To be more clear, does Android have an Email sender like C#. That would be the best solution if there isn't an API for this.
Now according to the updated firebase documentation
Here is how to send a verification mail to the user that in your case is after creating the account and letting the user to log-in then send him/her a notification that he have to verify the account and then the next login is blocked until he/she didn't verify (I think this is better than making the user is forced to open his email first)
Send a user a verification email
You can send an address verification email to a user with the
sendEmailVerification method. For example:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Email sent.");
}
}
});
You can now plug any Firebase gaps in email coverage by rolling your own email sender using Firebase Cloud Functions. There's an example here. Of course this means more work than just configuring like the built-in options but at least means we can do whatever we need to do. :)
I have recently switched to the new firebase. When I was using the legacy code I was able to reset the users email with no problem. Now with the new firebase I keep getting the error "An internal error has occurred. [ Error code: 13 ]". Even when I hit the password reset button on my app console I get the same error message on the console. I also followed all the instructions from the site on how to reset the users password.
Here is my code:
private void resetPassword() {
String email = mEmailEditText.getText().toString();
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.sendPasswordResetEmail(email)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(LoginActivity.this, R.string.sent_temp_password,
Toast.LENGTH_LONG).show();
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.i(TAG, e.getMessage());
}
});
}
Any help as to why this is occurring would be greatly appreciated!
I have also recently switched to the new Firebase console. I had many problems with authentication and I couldn't find any solutions. I backed up on a file the database and the rules, then I deleted the Firebase project and created a new one (from scratch, recreated the Firebase project, except for the database and the rules that I saved in advance). It worked. I guess there are many problems with converting a Firebase project from the old console to the new Firebase console.
If you don't find any other solution I recommend you do the same, it doesn't take too long.
In the new Firebase version, before any significant change in any user ( change the user's password or email, or delete the user) , the user must have signed in recently. so in order to guarantee a valid response you need to use the reauthenticate method before calling the change method...
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
// Get auth credentials from the user for re-authentication. The example below shows
// email and password credentials but there are multiple possible providers,
// such as GoogleAuthProvider or FacebookAuthProvider.
AuthCredential credential = EmailAuthProvider
.getCredential("user#example.com", "password1234");
// Prompt the user to re-provide their sign-in credentials
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.d(TAG, "User re-authenticated.");
//Here you can can insert your code
}
});
Just to clarify on my situation which is similar. This happens to all users. I don't have much dedicated to this database. Rebuilding, and will get back, but it's weird it was able to authenticate previously. Mind you I am not coming from an old firebase console to a new one. This project is a fresh new console.
I knew that we can verify the users email with Firebase Auth 3.0. I'm not able to find any documentation regarding email verification on Android. I'm able to find the same for iOS as well as web but not for Android. Any link to the documentation would be helpful.
From the image, it is clear that once the user signs in, he will be intimated regarding that on email to confirm his subscription. I've subscribed myself and also verified in the users section in Auth tab and I am able to see my mail id and firebase generated unique user id. What's missing here is the confirmation email to my email id. Did some one try this or am I too early trying this? Thanks for your help.
Email verification for android is now available in Firebase.
See this release note:
https://firebase.google.com/support/release-notes/android#9.6
Update
Email verification is available in version 9.6 and higher of the Firebase SDK for Android.
Original answer
Email verification is not available for Android yet. Also answered here with more context.
An alternative suggested by the Firebase team
One thing you could do is to add a node to your Firebase Database which contains all email addresses as children. You should make this node only publicly readable (via Firebase security rules).
Then from within your apps, once a user signs up / signs in, you check if the email of that user is on the list, and if not, you sign them out and kick them out of your app (and as a bonus, you could even log the intruder's email address in your database, so you can later check who is trying to access your app).
This will work for initial testing if you know the e-mail ids of the people who are gonna test your app until the e-mail verification makes its way to Android.
Since email verification only works with Email/Password authentication, the best place to send it wold be in the onComplete method of createUserWithEmailAndPassword(...) method, after signup is successful.
firebaseAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
sendVerificationEmail();
....
The custom sendVerification method is:
public void sendVerificationEmail() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(SignUpActivity.this, "Signup successful.
Verification email sent", Toast.LENGTH_SHORT).show();
}
}
});
}
}
You can then check if the user has verified their email anywhere in your app by calling:
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser != null ) {
Log.e(TAG, firebaseUser.isEmailVerified() ? "User is signed in and email is verified" : "Email is not verified");
} else {
Log.e(TAG, "onAuthStateChanged:signed_out");
}
}
};