Firebase Authorization Weird State after 24 Hours - ios

I understand that by default Firebase invalidates a login token after 24 hours. However, I am finding the behavior strange after this time period. When the app is run it checks to see if the user is logged in and if so it goes into the app otherwise it stays on the login screen:
if self.ref.authData != nil
{
self.performSegueWithIdentifier("mainTabSegue", sender: self)
}
This works fine unless the token has expired after 24 hours. What will happen then is that the app will still see that authData is not nil and it will send it to the next VC. The next VC makes uses of the UID which then causes the app to crash. Running the app again will then show that authData is in fact nil and the user will be asked to login as is expected.
So the question is why, after the 24 hour period, is authData not nil when the user is clearly not logged in? The Firebase documentation seems to indicate that checking authData as above is the correct way to determine whether a user is logged in.

Before your segue if you extract the uid from authData then you can pass that user to the first view controller. If you pass the user object to your first VC constructed in the App Delegate, then your app won't crash. I vaguely remember something similar happening to my app (i.e. where it thinks the user is logged in but then changes back to login). I'm not sure why this happened but it's possible the app tried to start where it left off?
You can also change the token expiration length on Firebase, as you may know.

Related

iOS firebase auth current user get nil when restart app

Auth.auth().signIn(withEmail:
In my case, When I first time open app and sign in firebase account like above code
then I reopen app
let user = Auth.auth().currentUser
user is not nil and then I reopen app get currentUser again user is nil that mean I did not sign in
I have the other app do like this, but the user always not nil.
I wonder why this happens.
Firebase automatically restores the authenticated user when the app restarts. But this requires a call to the servers, which may take some time. If you check Auth.auth().currentUser while the check is still in progress, you will get nil as the result.
To ensure you get the value once this initial check is done, use an auth state listener as shown in the first snippet in the documentation on getting the current user. From there:
Auth.auth().addStateDidChangeListener { auth, user in
// ...
}
Once this listener fires for the first time:
either the user variable will have a value if the user authentication state could be restored,
or it is nil if the user was not signed in last time the app ran, or the authentication state couldn't be restored (for example, because the account is disabled, or the password was changed).
I think it a big possibility you might be signed in on another device or signed in a different profile and didn't know, you might have some sync problems or security issues that did a safety measurement until you fix the security issue

What is the reason to save Firebase authVerificationID?

When logging a user in or signing the user up for the first time and using phone auth it says:
Save the verification ID and restore it when your app loads. By doing
so, you can ensure that you still have a valid verification ID if your
app is terminated before the user completes the sign-in flow (for
example, while switching to the SMS app).
I'm not exactly sure what is the purpose of saving it.
0- the user opens the app and they are on the Login screen
1- the user adds their phone number (below)
2- the callback receives the authVerificationID
3- before the user is taken to the SMS screen, the app is somehow terminated
4- when the user opens the app again, because they haven't logged in yet, they are right back on the Login screen. When they enter their phone number again, they receive either a brand new authVerificationID or the same one (I'm not sure), and they are taken to the SMS screen. Either way both are valid and will get them to the SMS screen.
What does saving the authVerificationID do when no matter what, if the app is terminated, they have to add their phone number again because they will be back on the Login screen?
If the answer is "check if the authVerificationID is saved, and if it is then bring them to the SMS screen instead of the Login screen" then that is bad ux. The user might come back an hour later, when they first open the app they will see the SMS screen and be confused.
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
guard let verificationID = verificationID else { return }
UserDefaults.standard.set(verificationID, forKey: "authVerificationID") // how does this help me?
// A. take user to sms view controller
// B. use authVerificationID && verificationCode for sms sign-in
}
The answer is pretty much what you said - if the user leaves your app in the middle of the auth flow, you can you can resume the sign-in flow from where they left off - i.e. the SMS verification step.
Once the user leaves your app, you have no guarantees that your app will not be terminated. It depends entirely on the OS. So your user might end up in a cycle where they just can't complete the sign-up (however unlikely this case is).
As for bad UX comment - it's very subjective (and depends on your design), and also time-dependent.

Automatically log out user when they leave the iOS app

I have an in-house app which is used by staff but the chances are the device it is used on could become consumer facing. With that in mind I want to ensure that should the staff forget to logout when they switch apps or just reopen the app that I have a command in there to effectively log them out.
After researching I think the best way for me would be to use:
optional func applicationWillEnterForeground(_ application: UIApplication)
and then force the app to go to the login page or the reverse so that when app enters background it forces the app to the logout URL.
Which do you think would be best and how can I use that command to then add in the chosen URL as described above?
So, while I agree with #Rakesha-Shastri in that ""app enters background it forces the app to the logout URL" This seems like bad UX. The first one where you display the login page on returning from background seems fine. It is important that the user is able to resume his work where he left off after logging in again," there does need to be a way, in-case a user is gone too long, that the credentials have passed. It seems in your case, that every time the user LEAVES or CLOSES the app, you want this to be unauthenticated. What if the user gets a phone call? Should it do that? You may want to use Timer, of say some period of time, 2-5 minutes maybe.
Any who, what you can do is force the user to have to RESTART the app, by either presenting a controller that has NO CAPABILITY of going anywhere, therefore forcing a restart, or providing a button that sends them to a login screen you have implemented.
Note:
I would definitely indicate to the user, "due to purposes of security, each time you exit the app, it requires an authentication to re-access. Please log back in". Then provide a button to the login screen.
As you did not provide code, and I'm not going to do this for you, a direction to take this would be to utilize optional func applicationWillEnterForeground(_ application: UIApplication) alongside with getting the current UIViewController. I would google how to do that. Then from there, you can create a new UIViewController that presents this button back to the login screen.

GameCenter - Login user if they already entered their credentials

In my game I don't want the GameCenter login popup appearing automatically when the app launches. So instead I have a GameCenter button that the user can tap to login with. When they press the button, the login screen appears.
However, it seems like when you launch the app again after logging in, the user still isn't "logged in". They still have to press the button again and then a little banner appears saying "Welcome back, User!". Is there a way to automatically relogin the user without them having to press the button each time? I already entered my credentials, why do I have to authenticate again?
Here is my code, when the user presses the button:
self.authenticatePlayer()
And here's the authenticate method:
func authenticatePlayer() {
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {
(view, error) in
if view != nil {
self.view?.window?.rootViewController?.presentViewController(view!, animated: true, completion: nil)
} else {
}
}
}
I need something that can welcome back the user if they already logged in, but NOT ask them to login if they haven't logged in already.
To understand the behavior you're seeing, we need to look at how the authentication process works.
It starts when you set the authentication handler. This is the signal that tells your app to try and talk to Game Center. The authentication handler's completion block has three possible conditions:
Error: something went wrong
Receives a view controller: the login view controller tells you the player isn't logged in
Receives nil view controller: the lack of an error + lack of a view controller tells you the player was already logged in.
Although IOS may be aware of your login state (or attempting to fake your login state using cached info), your app loses that context when you exit. When you startup again, there's been no attempt to set the authentication handler, thus no attempt to verify authentication status until your user presses the button, thus your app doesn't know whether the user is logged in or not.
I think the following approach will get pretty close to what you're looking for:
set the authentication handler and initiate the authentication as early as possible in your first viewController's viewDidLoad. Do this as early as possible in your start up sequence.
If the user isn't authenticated, you will receive a login view controller. Don't present it. Instead, save it. Don't present it unless/until the user presses the button.
If the user is already logged in, they will see the welcome back message as soon as the game starts, and you'll be able to proceed since the user is still logged in.

Swift + Parse - How to force app to refresh after logout

How do I refresh all my UIViews to show the data for the new user.
(Scenario: User1 logs out and User2 logs in without closing the app.)
Right now I have a Logout button on my userVC. Upon pressing it the current user is logged out and the login view is presented. If a new user logs in the view dismisses and shows the userVC again. The userVC, because it was never refreshed keeps showing the data of the old user. (This is also true for all other VCs in this tabbed application.)
How do I get the views to reload their data? (Or redraw?)
There are several ways you can achieve this, but the first thing you should do is add an ACL to your userdata so that User2 does not have access to User1's data! Security is something you must take seriously when handling data for multiple users.
More info: https://parse.com/docs/ios/guide#security
If you log in a user, you could call a method for fetching the data. How is the data for your view retrieved? Whatever code you're using to fetch user data for the view, make sure this code is in its own function so that you can call it again upon login.
Update
Call the getInfo() in viewWillAppear() or viewDidAppear() instead. If that is too often, you can set a flag when a user logs in so that getInfo() is called only if it's a newly logged in user.

Resources