tl;dr
(ID Token issued at 1589401401 is stale to sign-in.)
The problem:
My app using Google Sign-in with Firebase. After the user loged in, he have the option to remove his account which its also deletes his user from firebase auth. Sign in works totally fine. Deleting user from firebase also works as expected.
The error happens only when the user was logged-in while ago, an hour or so before he tries to delete his account.
ERROR deleting user: task fail
com.google.firebase.auth.FirebaseAuthInvalidCredentialsException:
The supplied auth credential is malformed or has expired.
[ ID Token issued at 1589401401 is stale to sign-in. ]
More details:
Firebase demands recent authentication before sensitive actions like account removing therefore i'm using "user.reauthenticate(credential)" before "user.delete()"
Removing user code flow:
user.delete() -> if error: FirebaseAuthRecentLoginRequiredException -> user.reauthenticate(credential) -> user.delete()
Whats weird is that re-authentication actually succeed if only about 30 minutes passed from the last log in but it fails if it's was about an hour or more. Also, it was working perfectly before but i can't manage to know whats changed that now i get this error
I'm assuming that I can just force the user sign in again using google sign-in but as far as I know it's not mandatory for google sign-in method as I get the user id token using: GoogleSignIn.getLastSignedInAccount() and pass the token id as credentials for reauthenticate()
My code:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private void userDelete() {
Log.d(TAG, "userDelete: Deleting user...");
user.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: User deleted");
Log.d(TAG, "userDelete: Signing out...");
signOut(); //Signing out from Firebase and Google log-in
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(TAG, "onFailure: Error deleteing user, probebly need to reauthenticate");
Log.e(TAG, "onFailure: Error:", e);
reAuthenticateUser(); //reauth and delete user
}
});
}
Re authenticating user if getting user deletion error:
private void reAuthenticateUser() {
Log.d(TAG, "reAuthenticateUser: Reauthenticating");
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
// Get the account
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(getContext());
if (signInAccount != null) {
AuthCredential credential = GoogleAuthProvider.getCredential(signInAccount.getIdToken(), null);
user.reauthenticate(credential).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Reauthenticated.");
Log.d(TAG, "onComplete: Try to delete user again...");
user.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: user deleted successfully");
Log.d(TAG, "onComplete: signing out...");
signOut();
}
});
} else {
Log.e(TAG, "onComplete: ERROR deleting user: task fail", task.getException());
}
}
});
} else {
Log.d(TAG, "Error: reAuthenticateUser: user account is null");
}
}
Signing out after User removal:
private void signOut() {
//sign out from firebase
FirebaseAuth.getInstance().signOut();
//sign out from "google sign in"
googleSignInClient.signOut().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
//Get back to login screen
Intent intent = new Intent(getContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
getActivity().finish();
}
});
}
The error:
D/Settings fragment:: onFailure: Error deleteing user, probebly need to reauthenticate E/Settings fragment:: onFailure: Error:
com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException: This operation is sensitive and requires recent authentication. Log in again before retrying this request.
at com.google.firebase.auth.api.internal.zzdx.zza(com.google.firebase:firebase-auth@@19.1.0:4)
at com.google.firebase.auth.api.internal.zzfa.zza(com.google.firebase:firebase-auth@@19.1.0:21)
at com.google.firebase.auth.api.internal.zzet.zza(com.google.firebase:firebase-auth@@19.1.0:34)
at com.google.firebase.auth.api.internal.zzev.zza(com.google.firebase:firebase-auth@@19.1.0:74)
at com.google.firebase.auth.api.internal.zzed.zza(com.google.firebase:firebase-auth@@19.1.0:18)
at com.google.android.gms.internal.firebase_auth.zza.onTransact(com.google.firebase:firebase-auth@@19.1.0:13)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994) D/Settings fragment:: reAuthenticateUser: Reauthenticating I/BiChannelGoogleApi: [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzao@da6aa2a E/Settings fragment:: onComplete: ERROR deleting user: task fail
com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The supplied auth credential is malformed or has expired. [ ID Token issued at 1589401401 is stale to sign-in. ]
at com.google.firebase.auth.api.internal.zzdx.zza(com.google.firebase:firebase-auth@@19.1.0:30)
at com.google.firebase.auth.api.internal.zzfa.zza(com.google.firebase:firebase-auth@@19.1.0:21)
at com.google.firebase.auth.api.internal.zzet.zza(com.google.firebase:firebase-auth@@19.1.0:34)
at com.google.firebase.auth.api.internal.zzev.zza(com.google.firebase:firebase-auth@@19.1.0:74)
at com.google.firebase.auth.api.internal.zzed.zza(com.google.firebase:firebase-auth@@19.1.0:18)
at com.google.android.gms.internal.firebase_auth.zza.onTransact(com.google.firebase:firebase-auth@@19.1.0:13)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994)
Also, here the (handled ) error I get if trying to remove user after about 15-30 minute from last log in. in this case the re authentication works as expected.
D/Settings fragment:: userDelete: Deleting user... I/BiChannelGoogleApi: [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@c066c75 D/Settings fragment:: onFailure: Error deleteing user, probebly need to reauthenticate E/Settings fragment:: onFailure: Error:
com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException: This operation is sensitive and requires recent authentication. Log in again before retrying this request.
at com.google.firebase.auth.api.internal.zzeh.zza(com.google.firebase:firebase-auth@@19.3.1:4)
at com.google.firebase.auth.api.internal.zzfo.zza(com.google.firebase:firebase-auth@@19.3.1:21)
at com.google.firebase.auth.api.internal.zzfe.zza(com.google.firebase:firebase-auth@@19.3.1:33)
at com.google.firebase.auth.api.internal.zzfg.zza(com.google.firebase:firebase-auth@@19.3.1:74)
at com.google.firebase.auth.api.internal.zzen.zza(com.google.firebase:firebase-auth@@19.3.1:18)
at com.google.android.gms.internal.firebase_auth.zza.onTransact(com.google.firebase:firebase-auth@@19.3.1:13)
at android.os.Binder.execTransactInternal(Binder.java:1021)
at android.os.Binder.execTransact(Binder.java:994) D/Settings fragment:: reAuthenticateUser: Reauthenticating I/BiChannelGoogleApi: [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@c066c75 D/FirebaseAuth: Notifying id token listeners about user ( OF22mQlCILNAirW9tN87SV8WAiY2 ). D/Settings fragment:: Reauthenticated. D/Settings fragment:: onComplete: Try to delete user again... I/BiChannelGoogleApi: [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@c066c75 D/FirebaseAuth: Notifying id token listeners about a sign-out event.
Notifying auth state listeners about a sign-out event. D/Settings fragment:: onSuccess: user deleted successfully
Thanks