Swift - Firebase Authentication State Persistence - ios

I'm currently thinking about implementing Firebase Auth to my Swift project, hence I've been reading some articles. - Namely among others this one.
I need some help understanding the given article. It's about "Authentication State Persistence". Does this mean, that if the value is set to local, the user will stay logged in even after closing the app? In other words, will he be able to sign up once and stay logged in until he decides to log out - even when he's offline?
Let's say a user decides not to create an account and logs in with "Anonymous Authentication" (I assume this is the type of login in this kind of case) - will he stay logged in forever as well or is there a danger of data loss, in case of going offline or closing the app?

First: the link you provided refers to a javascript firebase documentation
Second: the only thing available in IOS is you can create an anonymous user with
Auth.auth().signInAnonymously() { (authResult, error) in
// ...
let user = authResult.user
let isAnonymous = user.isAnonymous // true
let uid = user.uid
}
and you can convert it to a permanent user check This
Finally: whether the user is usual / anonymous , after you sign in you need to check this to show login/home screen every app open
if FIRAuth.auth()?.currentUser != nil {
print("user exists")
}
else {
print("No user")
}
and the user still exists unless you sign out regardless of whether you closed the app or not
If you are using the latest Firebase version, FIRAuth is now Auth:
if Auth.auth()?.currentUser != nil {
print("user exists")
}
else {
print("No user")
}

Related

Check if user already has an account just by email

How do I check if a user exists in my Firebase Database only by email within Swift?
The first screen the user should see allows him to type in his email. After that he gets to the sign up page or the login page depending on wether or not the user exists.
You're looking for fetchSignInMethodsForEmail, which returns the sign-in methods with which the given email is registered. With that information you can build a sign-in screen.
Try with this:
Auth.auth().fetchProviders(forEmail: email) { (providers, error) in
if error != nil {
print(error?.localizedDescription)
} else {
print(providers)
}
}
If the email address has not yet been used, the empty list (providers) will be printed.

How to check after login user is login through Facebook in firebase for ios swift?

My app is having facebook & email password login with firebase. Now for those user who are signed with Facebook, I don't want to verify their emails. but in Auth.auth().currentUser?.isEmailVerified its return false always. so is there any other method to detect user is logged in with facebook. I know i can store value inside user default before login but after uninstall & reinstall app i will lost that userdefault. while firebase keep user logged in. i can use keychain for that but if firebase directly provide that then that will make easy for coding.
I find one solution with firebase methods:
if let providerData = Auth.auth().currentUser?.providerData {
for userInfo in providerData {
switch userInfo.providerID {
case "facebook.com":
print("Facebook Login")
//isVerifiededUser = true
default:
print("provider is \(userInfo.providerID)")
}
}
}
You can use:
if let user = Auth.auth().currentUser {
if FBSDKAccessToken.current() != nil {
// logged in using facebook
}
else {
// logged in using manual email/password method
}
}
so you can send verification emails to only those who are logged in using email/password method.
Firebase doesn't provide a method to show which was the first method used to create Firebase account. You will have a list of the all the providers attached to a firebase user with their emails/ phone number attached to them.
Firebase by default only set emails verified for Google SignIn, for other providers Firebase behavior is to set false (although some times it do set the email verified true randomly). The reason is that Firebase cannot guarantee that email is verified by facebook on their platform but incase of Google firebase has trust.
One option is you always send verification email no matter facebook or Email Auth. Second is that you ditch Email password login and instead use new Email Link Authentication, which eliminates the email auth needed in password login.
EDIT:
if you only allow one method to be used at a time then you can get the providers list from the firebase user and check if the providers list has 'password' signin method present, send a verification email after checking email verified, else don't send the email and continue the app
Here is the resource to email link authentication: https://firebase.google.com/docs/auth/ios/email-link-auth
This code means that at some point the user registered using Facebook, but it does not mean that at this point the user is using this provider for access. If the user has these providers ["google.com", "facebook.com"] it will also return true . 😊🖤
fileprivate func userHasFBProvider() -> Bool{
var fBProvider = false
guard let providerData = Auth.auth().currentUser?.providerData else {
return fBProvider
}
for userInfo in providerData {
switch userInfo.providerID {
case "facebook.com":
fBProvider = true
default:
fBProvider = false
}
}
return fBProvider
}

Do authenticated user stay signed in when i just terminate app without signing out?

I am novice in Firebase, and I an currently trying to handle (upon loading app) if user is logged in.
So according to a book i have to check it like that:
if Auth.auth().currentUser?.uid == nil {
//do smth
}
So as it turns out(if i am not missed something and not wrong) it only checks the last user in Authentication section of a console. I mean if i registered user that way:
Auth.auth().createUser(withEmail: email, password: password) { (User, Error) in
if Error != nil {
print(Error)
return
}
And just terminate my app,then during my check it will see only the last registered user. And after detecting this signed in user and if i sign out then app won't see rest signed in users in the next checking procedure.
So it seems like:
I ran app then create user several times (create then terminate app and again create then terminate app and back again)
Then after step 1 and check if user signed in. Is this last user or 1st user i don't know because i did not found and detail info about it .
if Auth.auth().currentUser?.uid == nil {
//do sign out
do {
try Auth.auth().signOut()
} catch let logoutError {
print(logoutError)
}
}
It finds signed in user then i sing out this user.
I terminate app.
I run this app again and during initial check of signed in users it does not found any of them.
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
//user is not logged in
if Auth.auth().currentUser?.uid == nil {
signOut()
}
}
Why? I mean I did not sign out by myself the rest registered users, and I know upon calling createUser func, this createUser func also signs user in.
Maybe app signs out user if i create new? then why i did not found any info about this behavior( Please, if someone have any clue i would appreciate it.
Firebase Authentication users stay signed in until:
either your code signs them out explicitly
or you create another user in the same app on the same device
or until an event happens that requires them to sign in again (such as a password change)
A single app on a single device can only have a single signed in user. If you sign in (or create) another user on the same device, the previous user will be signed out.

Firebase Realtime Database Connection Refresh

I have two controllers one is login and another is tableView Controller where I am displaying users information.
When app starts it first checks if user is logged in or not.
If user is logged in, it will fetch users data from firebase realtime database and display in tableView. If not then it will show login controller where user have to login using email and password.
Now once i logged in i can see users data into TableViewController from firebase, But if i closed app without log out and open it after some time like 20 min later or next day when the app launch it check if user is logged in or not in my case it shows logged in and display tableViewController but it is empty it does not fetch users data from firebase realtime database.
If i will logged out and login again then i can see users data coming from firebase but if i close app and open it again after sometime it will not show any data into my tableViewController.
I dont want users to login every time in application to get firebase data if user is logged in it must show the data from firebase real time database.
Following is code to check if user is logged in or not
if Auth.auth().currentUser?.uid == nil{
print("Logout call")
perform(#selector(handleLogout), with: nil, afterDelay: 0)
}else{
print("User Logged In")
fethUserAndSetupNavbarTitle()
}
following code will get data from firebase realtime database.
guard let uid = Auth.auth().currentUser?.uid else {
return
}
let dbReference = Database.database().reference().child("Users").child(uid)
dbReference.observeSingleEvent(of: .value, with: { (snapshot)
in
if let dictionary = snapshot.value as? [String:AnyObject] {
let user = Users(dictionary: dictionary)
print("setup navbar called")
self.setupNavBarWithUser(user)
}
}, withCancel: { (error) in
print(error.localizedDescription)
return
})
Please let me know if i am unable to describe the problem.
Thank you in advance.
I might know what the problem is.
The Firebase Token gets disabled after one hour or so.
You need to enable Token Service API to allow refreshing the token once it expires.
Go to https://console.developers.google.com/ , click onto "Enable APIs And Services", search for Token Service API and enable it.

Is anonymous auth enabled by default?

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'

Resources