CloudKit Login Missing Acount - cloudkit

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

Related

Can you validate whether a user has been recently authenticated on Firebase (Swift)?

Is there a way to check if a user has recently authenticated on Firebase to avoid this message when trying to delete a user: "This operation is sensitive and requires recent authentication. Log in again before retrying this request."
I have been playing around trying to compare lastSignInDate (below) to current time but there seems to be a large margin of error on this which can cause problems:
firebase.auth().currentUser.metadata.lastSignInTime
Are there any functions that can return a simple boolean as to whether a user has recently authenticated so the user.delete() function will work properly?
Thanks so much!
The best way to do this is by checking if the response has an error, like so:
let user = Auth.auth().currentUser
user.delete { error in
if let error = error {
if (error.code == "auth/requires-recent-login") {
// The user's credentials are too old. Prompt Login screen.
}
} else {
// ...
}
}
According to Firebase Documentation, There's no other approach to this other than comparing the current date with firebase.auth().currentUser.metadata.lastSignInDate (Only if you have the Admin SDK on your app, but you most probably do not need that for enabling a user to delete themselves).

Test for account partially logged into cloudkit? "Update Apple ID Settings"

I've got an iOS app that is reliant on cloudkit for much of the functionality. However, I seem to be able to get in a state where the user is partially logged in. Basic cloudkit login checks pass, I can get my recordID, but I can't read or write to records like I can when I'm fully logged in.
Full details below - any ideas on how to identify this state without testing a read or write?
Upon launch of the phone, I get an 'Update Apple ID Settings' alert that states
"Some account services will not be available until you sign in again"
So, the issue is clearly related to that (which seems to be frequent with the simulator...). If I got to my settings and re-enter my password, all is well with the world. I can deal with this by error handling on an attempt to read or write, but I'd rather check in advance and warn the user appropriately.
How I check today:
At launch, I check to see if the user is logged in to cloudkit:
if FileManager.default.ubiquityIdentityToken != nil {
print("User logged in") // IT PASSES IN THIS STATE
}
else {
print("User is not logged in")
}
So far, so good. The test passes, the user is logged in. However, when I go to read or write, it is clear that I'm NOT logged in. For example, I'll get a CKErrorPermissionFailure when trying to write.
Additional note - in the current, 'partially'? logged in state, the below returns the correct recordID for my user:
let container = CKContainer.default()
container.fetchUserRecordID() { recordID, error in
Any ideas on how to programatically identify this partial state for cloudkit? Thanks!
I haven't found an answer that will address this, but wanted to document two things that could be of use
While the status check returns active, if I then try to fetch a record that requires you to be logged into iCloud, it fails and I can use that failure to determine logout status.
The other issue I've run into is a handful of users that have iCloud turned on but do NOT have iCloud Drive enabled for some reason. You can check for that with the approach below:
CKContainer.default().accountStatus { (accountstatus, error) in
switch accountstatus {
case .noAccount:
log.error("user logged out of iCloud OR iCloud Drive off")
case .restricted:
print("restricted")
case .available:
print("user logged into iCloud and iCloud drive")
case .couldNotDetermine:
log.warning("could not determine account status")
default:
log.error("New account status returned")
}
}

Does deleting account from Firebase automatically logs user out?

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

Parse user not updating for just one specific user

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.

Checking if person opening app is already an authenticated user FirebaseAuth swift

I have an app that uses Facebook authentication to login. When the onboarding screen is loading I check to see if the user is already authenticated and perform a segue to the home screen if they are using the code below:
override func viewDidLoad(animated: BOOL) {
super.viewDidLoad(animated)
if FIRAuth.auth()?.currentUser != nil {
performSegueWithIdentifier(loginSucessIdentifier, sender: self)
}
}
The thing is, if I create a test user on facebook and then sign into the simulator device with the test user login info, when I open the app it still says I am the user, not the test user and when I go to Main screen it still pulls up my info.
I checked all the examples and docs for firebase and can't find a place where they do this initial check.
Can anyone explain if I am doing the check wrong or if there is something with the facebook test user I am not doing properly.
Thanks
I finally figured out what the problem was. When a user clicks the signout button you also need to log out of facebook with FBSDKLoginKit. So when I signed back in it was still reading the credential from previous user facebook login.
let loginManager = FBSDKLoginManager()
loginManager.logOut()