Im running Parse Server on heroku and mLab and I use the following code to delete a user:
if PFUser.current() != nil {
PFUser.current()?.deleteInBackground(block: { (success, error) in
if error == nil {
self.performSegue(withIdentifier: "unwindToLoginFromSignUp", sender: self)
} else {
// Handle error
}
})
}
The issue is that after deleting a user if I create a new user I get the error "Invalid session token (Code: 209, Version: 1.14.2)". I understand what a session toked is but I'm not sure how I should be handling it when I delete a user.
Also the error does not cause a crash, it just shows up in the console. Any help is much appreciated!
I think you should store the currentUser object then log out the user first, and then delete the currentUser.
Once you delete the user without deleting the session, the app won't know that the current user doesn't exist any more, the session still remains, therefore you will get a session error after signing up another user.
But if you log out the user first, the current session will also be deleted, then you are free to create a new user.
I realized I forgot to log the user out after deleting their account and taking them back to the sigh up view.
Related
I've done this before and not had any problems. All I'm doing is deleting the current user and if that is successful logging them out and going back to the sign up view. I use the below code. This is the issue.
If a user signs up, I can delete and log them out successfully once. But if another user is created and I try to delete and log them out the user is deleted and when the logout attempts I got the error: Invalid session token.
Any help is much appreciated. Also please let me know if theres any other relevant code I can add.
PFUser.current()?.deleteInBackground(block: { (success, error) in
if error != nil {
print(error)
} else {
PFUser.logOutInBackground(block: { (error) in
if error != nil {
print(error)
} else {
self.performSegue(withIdentifier: "showLoginSignupView", sender: self)
}
})
}
})
I'm surprised this would work even the first time. If you've deleted a user, there is no user to log out. Try switching the order of those functions. Sign them out, then delete the user. You may need a cloud function for this so that the User can be deleted with the master key, as users should not have public destroy permissions.
I have failed to find some info on this, but it seems that even though I do not force the user to auth(⚠️) at all, it seems as if I call FIRAuth.auth()?.currentUser at least a few seconds after startup, I will get a valid anonymous user back. Does the Firebase SDK log the current user in behind the scenes, or is an unauthed user always regarded anonymous?
⚠️ auth as in:
FIRAuth.auth()?.signInAnonymously() { (user, error) in
if error != nil {
print("Sign in anonymously failed: \(error)")
return
}
if let user = user {
print("user: \(user), is anon: \(user.isAnonymous), uid: \(user.uid)")
self.user = user
}
}
Update 1: It seems I may be wrong, or there is something else important here. It might be the case where a device that has previously signed in will subsequently always (or something... maybe using keychain etc) be treated as signed in, even if app is deleted between runs. Investigating...
Update 2: So after some investigation 🕵🏻 it seems that if we don't sign the user out specifically, the user will likely remain signed in forever OR at least a long time. Even between installs... I swear I tried to delete then install, and the user was still signed in...
No, you must enable anonymous authentication in the Firebase console in the 'Authentication' tab, under 'Sign In Method'
Straight from the documentation, it says that:
PFUser#currentUser() gets the currently logged in user from disk and
returns an instance of it.
This is fine and all, but what if the user logged in # disk isn't a user that's logged in on the server. Lets say the users account has been deleted for whatever reason, or the session is no longer valid due to database modifications. These are currently the problems that I'm facing.
Throughout the tutorials that I've read, I've seen using the following line of code as a way to check if the user is valid, and thus you can skip the login stage of the application:
if let user = PFUser.currentUser() as? Subclass {
// Simulate successful login
}
However, this is posing a problem for me, as the successful login is simulated, but the login was not successful. Here is the error I'm dealing with:
[Error]: invalid session token (Code: 209, Version: 1.12.0)
So the first thing I did was attempt to log the user out, however this fails (I assume because the user wasn't logged in to begin with) and now I'm thrown into application which immediately crashes because the data required by the server isn't there. Here's how I attempted to handle error code 209:
let query = PFQuery(className: "Foo")
query.whereKey("Bar", equalTo: "Foo")
query.findObjectsInBackgroundWithBlock {
(foo, error) -> Void in
if let error = error {
print(error);
if error.code == 209 {
PFUser.logOutInBackgroundWithBlock {
(error) -> Void in
if let error = error {
print("Okay, I'm trapped!");
}
}
}
}
}
The output of this "query" is the following:
[Error]: invalid session token (Code: 209, Version: 1.12.0)
Okay, I'm trapped!
I'm out of ideas over here, and I'm ripping my hair out trying to figure out how to properly validate a user upon application launch. It seems redundant to have to catch error code 209 on every query, but if that's what you have to do, then that's what you have to do.
You can use synchronous logout. So even if error occurs, it doesn't matter. The PFUser session token will be invalidated if the user launches the app again.
Also latest Parse SDK provides PFConstants class, which provides enum for all possible error cases.
kPFErrorInvalidSessionToken = 209.
if (error.code == kPFErrorInvalidSessionToken) {
PFUser.logOut()
//Necessary pop of view controllers after executing the previous code.
}
I'm implementing parse login in iOS using swift. From a login view controller i get new users to signup via swift using just email and password. This creates a PFUser which correctly saves to Parse backend. The user is then taken to a UserDetails view controller to "complete" their signup by providing more details which gets saved to coredata (im using parse functionality just for the signup). If the user cancels however before "completing" the additional details, I want to delete the PFUser from parse created possibly moments earlier. In the UserDetails view controller under cancelTapped ibaction im running code
if PFUser.currentUser() != nil {
PFUser.currentUser()?.deleteInBackgroundWithBlock({ (deleteSuccessful, error) -> Void in
print("success = \(deleteSuccessful)")
})
//user deleted in background block above but still logged in so now logout
PFUser.logOut()
}
but im getting following parse error [Error]: User cannot be deleted unless they have been authenticated. (Code: 206, Version: 1.8.5) .... i dont know what authentication process is needed and im guessing the problem could be because im trying to delete a user before parse has had a proper time to create the user in the first place .... any help or suggestions appreciated
User ALC permission automatically blocks anyone else from performing a write/delete on your record. This means you must be logged in if you want to update/delete your own record. In your code, you probably log out before your asynchronous delete code gets a chance to run in the background. Instead you need to log the user out after the delete was successful in the completion block of deleteInBackgroundWithBlock function.
if PFUser.currentUser() != nil {
PFUser.currentUser()?.deleteInBackgroundWithBlock({ (deleteSuccessful, error) -> Void in
print("success = \(deleteSuccessful)")
PFUser.logOut()
})
}
I have a couple hundred users that I need to remove from my parse app. However, when I delete the user accounts the users are still able to use the app fully without a problem. Is there anyway to "force" the logout remotely? Or what else would you suggest? Thanks!
It sounds like the user is being cached on the device and I don't think parse has a remote way to clear cached data on there. I like to put a user refresh(now fetch since refresh is deprecated) function when app opens to get the latest data for that user.
You could put a fetch function when the app opens and if it returns a specific error, it would mean the user doesn't exist and then set the current user to nil. I'm not sure which error it returns and I'm at work so I can't try it right now. I would hope that if the user doesn't exist, it would return kPFErrorUserWithEmailNotFound = 205...
Here are the error codes: https://parse.com/docs/ios/api/Constants/PFErrorCode.html
You will have to give it a try but I am thinking something like this (sudo-code):
post.fetchIfNeededInBackgroundWithBlock {
(post: PFObject?, error: NSError?) -> Void in
if let someError = error {
if someError = kPFErrorUserWithEmailNotFound {
// User doesn't exist!
}
} else {
// User exists and is fetched successfully
}
}