When the user logs in with Gmail or Facebook, they are taken to a page to input more information about their account (since Gmail or Facebook alone does not provide the information about the user that is needed) and after the user inputs this information, the user is logged in with that provider into firebase, and their information is saved into the firebase real-time database.
My question is, when the user goes back to login again with that account, they are taken to the page to input information that has already been inputted. So how do I find out whether the user has already signed up with Facebook, or Gmail so that I can bypass this screen and go straight to the app?
I was thinking of simply logging in the user with the respected provider as soon as the provider login is complete, then check the userID against one created in the database to see if it exists, and if not, take them to the screen to input data. However, with this approach I am worried that if a user gets to this input data screen, then closes the app and reopens it, the user will be logged in without this information. Is there another way of doing it? thank you!
the way I sign in with facebook:
FBSDKLoginManager().logIn(withReadPermissions: ["email"], from: self) { (result, err) in
if err != nil {
print("Custom FB Login failed:", err)
self.popup.showUnsuccessfullAlert(message: "Failed to login with facebook")
return
}
print("the result from logging in = \(result)")
self.showEmailAddress()
}
and the way I sign in with google:
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let err = error {
print("falied to log into google", err)
self.popup.showUnsuccessfullAlert(message: "Failed to login with google")
return
}else{
print("successfully logged into google ", user)
self.gmailUser = user
performSegue(withIdentifier: "toSignUpGmail", sender: nil)
}
}
You can use this method on your AppDelegate.swift file.
func applicationWillEnterForeground(_ application: UIApplication) {
//check if the user exists here and do something about it.
}
This function will execute every time the user opens the app after closing it.
Related
My application uses the microphone's permission, which is requested in another framework, and in the main application, I wasn't able to observe when microphone permission changed. I tried using KVO's observer but the application doesn't receive any events when the microphone permission is changed.
private var permissionStatusObserver: NSKeyValueObservation?
private func observeRecordPermissionChange() {
do {
try audioSession.setActive(true)
permissionStatusObserver = audioSession.observe(\.recordPermission) { [weak self] _, recordPermissions in
print("recordPermission changed")
}
} catch {
print("active audio failed \(error.localizedDescription)")
}
}
Not going to work.
There are 3 possibilities:
App never asked user for permissions yet. In this case you should present permissions to the user and wait for their response. In this case you need to define requestRecordPermission callback instead of listening to KVO.
App previously asked user for permissions, and user granted them. In this case you can proceed working with microphone.
App previously asked user for permissions, and user denied. Typically in this case apps show the message telling user to go to settings. And user needs to go to Settings -> Privacy -> Microphone and reenable the permissions, at which point the app will be restarted. So nothing to listen to as #cora mentioned.
Something like this:
switch AVAudioSession.sharedInstance().recordPermission {
case .granted:
// start recording
case .denied:
// Present message to user indicating that recording
// can't be performed until they change their preference
// under Settings -> Privacy -> Microphone
case . undetermined:
// Ask for permissions as explained below.
}
Or you can always ask for permissions like Apple tells us to:
// Request permission to record.
AVAudioSession.sharedInstance().requestRecordPermission { granted in
if granted {
// The user granted access. Present recording interface.
} else {
// Present message to user indicating that recording
// can't be performed until they change their preference
// under Settings -> Privacy -> Microphone
}
}
This is safe to do even if the permission is already granted (the callback will be back very quickly).
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
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()
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)
}
}
How can I associate a user's device with my app? I want to have it so the user doesn't create an account but their data is still saved and retrieved to their phone so I need a way to associate their phone with my app. I'm using Parse to save user data.
I'm trying to use device token and I'm wondering if this is the correct approach. Any ideas would be greatly appreciated.
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.save()
}
You can simply use anonymous users with Parse. They've introduced them a few years because you can't get the UDID anymore and still may want to identify your users.
You can simply login an anonymous user on startup with the following command:
if (![PFUser currentUser]) { //we check if the user is already logged in
[PFAnonymousUtils logInWithBlock:^(PFUser *user, NSError *error) {
if (!error) {
//user has been logged in
}
}];
}
This will create an anonymous user in your userbase and they will be able to write data to your database. Anonymous users can be logged out and behave like normal users. There is also a possibility to merge them to a signed up user.
Here is a blog post from Parse, with some additional information. Their docs are usually also quite helpful.
EDIT: in case you have trouble converting the code to swift, here is the equivalent code in swift (taken from the docs, available here):
PFAnonymousUtils.logInWithBlock {
(user: PFUser?, error: NSError?) -> Void in
if error != nil || user == nil {
println("Anonymous login failed.")
} else {
println("Anonymous user logged in.")
}
}