I would like to know, does deleting account from Firebase automatically logs user out? I mean, if I want to show him after deleting the login screen, then I just have to present that VC? I am asking this because if I do like this, it crashes and I think it is because the user doesn't exists anymore at this points. Am I right?
The code with some explenations :
let user = FIRAuth.auth()?.currentUser
user?.deleteWithCompletion { error in
if let error = error {
// An error happened.
} else {
try! FIRAuth.auth()!.signOut()//This is unnecessary?
let mainStoryboard: UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
let WelcomeViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "WelcomeViewController")
//Send the user to the WelcomeViewController
self.present(WelcomeViewController, animated: true, completion: nil)
// Account deleted.
}
}
If you are deleting your currentUser you need to take care of two things:-
Delete the user's data from the Firebase Database (If there is any)
Delete the auth Credentials (e.g :- email-password, facebook login, twitter etc)
To delete your current user use the below function, which also first sign's out the user
FIRAuth.auth()?.currentUser?.delete(completion: { (err) in
print(err?.localizedDescription)
})
If you CMD+CLICK on the delete function it will take you to its documentation :-
Deletes the user account (also signs out the user, if this was the current user).
completion Optionally; the block invoked when the request to delete the account is complete, or fails. Invoked asynchronously on the main thread in the future.
Possible error codes:
- #c FIRAuthErrorCodeRequiresRecentLogin - Updating email is a security sensitive operation that requires a recent login from the user. This error indicates the user has not signed in recently enough. To resolve, reauthenticate the user by invoking reauthenticateWithCredential:completion: on FIRUser.
See #c FIRAuthErrors for a list of error codes that are common to all FIRUser operations.
*/
So long story short if the err received is nil your current users's account has not only been deleted but also signed out automatically, But you will need to handle other FIRAuthErrors as stated in the documentation
Related
if let cachedUser = PFUser.current() {
// proceed to save some objects
} else {
PFAnonymousUtils.logIn{ (user, error) in
// proceed to save some objects
if ((error as NSError).code == 209) {
// session expired, logout and call PFAnonymousUtils.logIn again later
PFUser.logOut()
}
}
}
For a simple Swift mobile app, we save data on parse backend anonymously. If there is session expiration error (1 year default on Parser server), we will have to do something about it or we wont be able to save anything anymore. We therefore logout and re-login again.
Once we logout and re-login again, this creates a second new User on the backend.
This creates a problem - we no longer have an accurate picture of the number of users on the backend.
What was wrong in the flow above? Is there a way to prevent duplicated anonymous user when handling expired session?
It is possible to increase the default session duration in your server configuration.
You can also add the code below to your server configuration...
expireInactiveSessions: false
This thread may provide further useful insights into this issue.
When I want to delete a firebase user account in my application, the operation passes normally if the user has recently logged but after a period of time if I try to delete the user I get this error
"This operation is sensitive and requires recent authentication. Log in again before retrying this request."
Normally the firebase refresh the user session automatically but I didn't find why he want the user to log again and even the value of Auth.auth().currentUser is not nil. Thank you for your help !
this is my code to delete the user account :
#objc func deleteAccountAction(){
self.showProgressView()
let user = Auth.auth().currentUser
let id=Auth.auth().currentUser?.uid
self.refProducts.child(id!).removeValue { error, _ in
if(error != nil){
print("firebase remove error")
print(error?.localizedDescription.description ?? nil)
self.dismissHUD(isAnimated: true)
}
else{
self.refUsers.child(id!).removeValue { error, _ in
if(error != nil){
print("firebase remove error")
print("error while deleting user from firebase: "+error!.localizedDescription)
self.dismissHUD(isAnimated: true)
}
else {
user?.delete { error in
if error != nil {
print("error while deleting user:" + error!.localizedDescription)
self.dismissHUD(isAnimated: true)
} else {
UserDefaults.standard.removeObject(forKey: "USER_UID")
UserDefaults.standard.synchronize
self.dismissHUD(isAnimated: true)
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "StartingViewController") as! StartingViewController
nextVC.isAccoundDeleted=true
GlobalVar.user=nil
self.navigationController?.pushViewController(nextVC, animated: true)
}
}
}
}
}
}
}
For certain sensitive operations (such as changing the user's password, or deleting the user account), Firebase requires that the user has recently signed in. If the user hasn't signed in recently when you try to perform such an operation, Firebase throws the exception you get.
When you get this exception, you should ask the user to re-enter their credentials, and retry the operation.
From the documentation on handling errors:
[Deleting a user account] is a security sensitive operation that requires a recent login from the user. This error indicates the user has not signed in recently enough. To resolve, reauthenticate the user by invoking reauthenticateWithCredential:completion: on FIRUser.
In addition to Frank van's answer, time span for that is 5 minutes. After 5 minutes of login you cannot do such operations.
you can refer FIRAuthErrorCode (check out error code 17014 : FIRAuthErrorCodeRequiresRecentLogin = 17014)
Here is a workaround:
Make a call to a cloud function that performs the user account deletion and sign out the client. You must ensure proper guards for this cloud function so that it is not maliciously used.
Show courtesy to your users. Offer them with a proper dialog showing that this is irreversible and all relevant user data will be deleted permanently. Only call the function if the user accepts the consequences.
PSA edit:
Although this approach will work, it will have an improper risk imposed on your user profile and data. The requirement to have the user sign in again for the delete account procedure serves a higher objective which is an additional layer of protection for the user account. By bypassing it as the solution suggests you are imposing a risk that another actor using the device will be able to delete the account without any additional checks. it is a procedure that is irreversible so if it was done by mistake then there is no way to go back.
What you can do (its probably the most easy way) is to save login and password of the user in the local storage when they log in first time (for example using AsyncStorage) and once they want to delete the account log them in again without needing them to reenter credentials shortly before you delete the account. They wont even noticed you logged them in again before deleting the account.
Im not a security expert but the password and email would be stored localy without access to the outside world so I do not see any concerns about security issues there.
Once you delete the app, the local storage is gone anyways, at least with AsyncStorage.
Once you logout a user and use another account, the new account credentials would overwrite the old ones from the local storage.
I was wondering if anyone has seen a case where Parse User table doesn't update for a specific user. I have a pretty simple code:
PFUser.current()?["TorF"] = true
PFUser.current()?.saveInBackground(block: { (success, error) in
if error != nil {
print(error)
} else {
}
})
I have checks in other places of the app regarding whether there is a current PFUser, and my database shows that the user is logged in and PFUser.current() is correctly assigned to this user. The simple operation above works for all other users except for one specific user. Has anyone encountered something like this?
I found out that this was happening because the user had changed his password and therefore invalidated his access token. The place to check for whether the user's access token is valid is via Graph request.
Hi i'm trying to start working with Firebase and Swift, but i'm having some troubles authenticating users and making it persistent across app restarts.
I'm using Twitter authHelper which when authenticated returns a FAuthData object containing the user's uid and all those things.
The thing is when i (or the system) kill the app all the authentication thing blows away and i need to relogin because i'm not storing the "authData" object.
How should i do it?
Thank you so much
The best way to do this is using NSUserDefaults. This can be done in the following way (this assumes you are using FIRAuth but Twitter login will give you the same authData):
FIRAuth.auth()!.createUserWithEmail(email, password: pwd, completion: { authData, error in
if error == nil {
//enable automatic login for future usage
NSUserDefaults.standardUserDefaults().setValue(authData?.uid, forKey: "uid")
})
When the user opens the app the next time, do the following check to see whether or not the user has logged in before:
if NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) != nil {
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier(SEGUE_LOGGED_IN, sender: nil)
}
}
When a user is not signed to Game Center a UI pops up in the app. If a user is logged in to iCloud the app gets the cloudkit user ID. However, I do not understand what happens if the user is not logged in to iCLoud at all. As far as I can tell the app does not promt the user. Is there a way to do this?
Thanks,
Henry
You have to test for that yourself and take the appropriate actions. For testing the status you can use the code below. At the line where the account status is logged you could show an alert where you point the user to the settings app.
container = CKContainer.defaultContainer()
database = container.publicCloudDatabase
container.accountStatusWithCompletionHandler({status, error in
if error != nil {
NSLog("Error: Initialising EVCloudKitDao - accountStatusWithCompletionHandler.\n\(error!.description)")
} else {
self.accountStatus = status
}
NSLog("Account status = \(status.hashValue) (0=CouldNotDetermine/1=Available/2=Restricted/3=NoAccount)")
})
NSLog("Container identifier = \(container.containerIdentifier)")
The code above is a snippet from EVCloudKitDao