I implemented a google sign in in ios app. Now, how can I verify if user is logged in and if not - return him to the login page with Swift?

google sign-in integration in ios swift 4
custom google sign in button ios swift
google sign in swiftui
google sign in swift package manager
login with google ios firebase
presentingviewcontroller must be set google sign in swift
google sign in integration in ios swift stackoverflow
firebase authentication ios

As I wrote in the title of this question - I went through this tutorial https://developers.google.com/identity/sign-in/ios/sign-in and now I'm able to log in the user to my app based on his google credentials.

The way I do it so far is that I have a ViewController.swift class with the following code:

class ViewController: UIViewController, GIDSignInUIDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        let background = CAGradientLayer().greenBlue()
        background.frame = self.view.bounds
        self.view.layer.insertSublayer(background, atIndex: 0)
        //GIDSignIn.sharedInstance().uiDelegate = self

        // Uncomment to automatically sign in the user.
        //GIDSignIn.sharedInstance().signInSilently()

    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        GIDSignIn.sharedInstance().uiDelegate = self

        GIDSignIn.sharedInstance().signInSilently()
    }

    @IBAction func didTapSignOut(sender: AnyObject) {
        GIDSignIn.sharedInstance().signOut()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func signInWillDispatch(signIn: GIDSignIn!, error: NSError!) {
        print("Nothing!")
    }

    // Present a view that prompts the user to sign in with Google
    func signIn(signIn: GIDSignIn!,
        presentViewController viewController: UIViewController!) {
            self.presentViewController(viewController, animated: true, completion: nil)
    }

    // Dismiss the "Sign in with Google" view
    func signIn(signIn: GIDSignIn!,
        dismissViewController viewController: UIViewController!) {
            self.dismissViewControllerAnimated(true, completion: nil)
    }
}

and in my AppDelegate.swift class I have:

class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

    var window: UIWindow?


    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Initialize sign-in
            var configureError: NSError?
            GGLContext.sharedInstance().configureWithError(&configureError)
            assert(configureError == nil, "Error configuring Google services: \(configureError)")

            GIDSignIn.sharedInstance().delegate = self

            return true
    }

    // [START openurl]
    func application(application: UIApplication,
        openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
            return GIDSignIn.sharedInstance().handleURL(url,
                sourceApplication: sourceApplication,
                annotation: annotation)
    }
    // [END openurl]

    @available(iOS 9.0, *)
    func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
        return GIDSignIn.sharedInstance().handleURL(url,
            sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as! String?,
            annotation: options[UIApplicationOpenURLOptionsAnnotationKey])
    }

    // [START signin_handler]
    func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
        withError error: NSError!) {
            if (error == nil) {
                print("Signed in!")
            } else {
                print("\(error.localizedDescription)")

            }
    }
    // [END signin_handler]

    // [START disconnect_handler]
    func signIn(signIn: GIDSignIn!, didDisconnectWithUser user:GIDGoogleUser!,
        withError error: NSError!) {
            // Perform any operations when the user disconnects from app here.
            // [START_EXCLUDE]
            NSNotificationCenter.defaultCenter().postNotificationName(
                "ToggleAuthUINotification",
                object: nil,
                userInfo: ["statusText": "User has disconnected."])
            // [END_EXCLUDE]
    }
}

My storyboard looks as follows:

On the left I have a ViewController with marked google button (which is white, therefore it's not visible here - sorry!) and on the right I have a main TabController view that contains the whole logic of my app (so far it's quite empty):

class TabController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let background = CAGradientLayer().greenBlue()
        background.frame = self.view.bounds
        self.view.layer.insertSublayer(background, atIndex: 0)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

Now it works like this:

I run the app and see the google button to sign in. I sign in and when everything is validated - nothing changes, I'm not moving to the second screen (TabController). I just stay on this view and I can keep clicking the google button - nothing changes though because I'm already signed in.

I want to achieve a situation when the user opens my app and when he is not logged in - he sees the ViewController screen. When he logs in - he sees the TabController screen. And also when he already signed in before and opens my app - he immediately jumps to TabController and skips the ViewController page. How can I achieve it?

I suspect I have to mark on my storyboard my TabController to be the initial view controller, but what about the log in screen?

=====EDIT

following Mac Bellingrath answer I modified my function in appDelegate.swift class, now it looks like this:

func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Initialize sign-in
        var configureError: NSError?
        GGLContext.sharedInstance().configureWithError(&configureError)
        assert(configureError == nil, "Error configuring Google services: \(configureError)")

        GIDSignIn.sharedInstance().delegate = self

        /* check for user's token */
        if GIDSignIn.sharedInstance().hasAuthInKeychain() {
            /* Code to show your tab bar controller */
            print("user is signed in")
            let sb = UIStoryboard(name: "Main", bundle: nil)
            if let tabBarVC = sb.instantiateViewControllerWithIdentifier("TabController") as? UITabBarController {
                window!.rootViewController = tabBarVC
            }
        } else {
            print("user is NOT signed in")
            /* code to show your login VC */
            let sb = UIStoryboard(name: "Main", bundle: nil)
            if let tabBarVC = sb.instantiateViewControllerWithIdentifier("ViewController") as? ViewController {
                window!.rootViewController = tabBarVC
            }
        }

        return true
}

Now when I run the app and the user has been signed in before - I see the tabController view. If he wasn't signed in before - I see the ViewController view. It works almost like a charm, but I realized that no matter if I write if GIDSignIn.sharedInstance().hasAuthInKeychain() { or if !GIDSignIn.sharedInstance().hasAuthInKeychain() { it always prints out the message user is signed in, so something is still not right...

According to Google's documentation, it appears that you can use GIDSignIn's instance method hasAuthInKeychain() to check whether the user has either currently signed in or has previous authentication saved in keychain.

So, in your AppDelegate's

func application(application: UIApplication,didFinishLaunchingWithOptions                    launchOptions: [NSObject: AnyObject]?) -> Bool {

You might write something like:

GIDSignIn.sharedInstance().delegate = self
/* check for user's token */
if GIDSignIn.sharedInstance().hasAuthInKeychain() {
/* Code to show your tab bar controller */
} else {
/* code to show your login VC */
}

for example if our user is signed in:

let sb = UIStoryboard(name: "Main", bundle: nil)
if let tabBarVC = sb.instantiateViewControllerWithIdentifier("MainTabBarVC") as? UITabBarController {
window.rootViewController = tabBarVC
}

*Substitute your UITabBarController subclass for UITabBarController.

Of course, there are many ways to change the flow. Check out storyboard reference and multiple storyboards.

Integrating Google Sign-In into your iOS app, After you have signed in a user with Google, you can get the user's ID string, name, profile image, and email address. Objective-C Swift Once the user has authenticated and authorized access to the scopes you request, you can access user information if (error.code == kGIDSignInErrorCodeHasNoAuthInKeychain) { Important: If you need to pass the currently signed-in user to a backend server, send the user's ID token to your backend server and validate the token on the server. Add the sign-in button. Next, you will add the Google Sign-In button so that the user can initiate the sign-in process.

let googleUser = GIDSignIn.sharedInstance().isCurrentUser

if googleUser != nil {
// Get new token from google and send to server
let strToken = googleUser.authentication.idToken
} else {
// present login screen here
presentLoginScreen()
}

Getting profile information, You can use Firebase Authentication to sign in a user by sending them an email The ability to authenticate a user while also verifying that the user is the If you haven't yet connected your app to your Firebase project, do so from the Firebase is to be opened via a specified mobile app (for example, example. page.link ). To use Google Sign-in in your app, add a GIDSignInButton view to your app's sign-in screen.. Then, register your sign-in screen's view controller with the shared GIDSignIn object:

Mac Bellingrath given perfect answer for verify user is logged in.

Alternate way to check user logged in.

Here is sample code in Objective-C you can convert code as per your requirement.

This sample code is just for your reference.

    // The authentication object for the current user, or |nil| if there is currently no logged in user.
    // Here you can get current user object
    GIDGoogleUser *googleUser = [[GIDSignIn sharedInstance] currentUser];

    if (googleUser) {
        // Get new token from google and send to server
        NSString *strToken = googleUser.authentication.idToken;
    }
    else {
        // present login screen here
        [self presentLoginScreen];
    }

Authenticate with Firebase Using Email Link in iOS, You can let your users authenticate with Firebase using their Apple ID by You will also need to meet these requirements to test your integration with Sign In with Enable Sign In with Apple for your app on the Certificates, Identifiers & Profiles page If you are only using Sign In with Apple in an iOS app, you can leave the � After a successful sign in, every iOS app can use the access token (and refresh token) to make authorized requests, and most importantly developers can focus on the application logic only. If you want to read more about the OAuth 2.0 protocol, Google provides a nice documentation page for this reason.

Authenticate Using Apple on iOS - Firebase, iOS Apps Track Our login flow will allow new users to sign up and existing users to login. When a new user opens the app for the first time, we want them to see the login Create a new LoginViewController.swift class: The view controller screen we land on is white, not orange. makeKeyAndVisible() } return true }. 7 I implemented a google sign in in ios app. Now, how can I verify if user is logged in and if not - return him to the login page with Swift? Now, how can I verify if user is logged in and if not - return him to the login page with Swift?

Implementing Login Flow, I implemented a google sign in in ios app. Now, how can I verify if user is logged in and if not - return him to the login page with Swift? - ios. An unverified app is an app or Apps Script that requests a sensitive or restricted OAuth scope, but hasn't gone through the Google verification process. Users of unverified apps or your test builds might get warnings based on the OAuth scopes you're using.

I implemented a google sign in in ios app. Now, how can I verify , After a successful sign in, every iOS app can use the access token (and If you need user authorization for many scopes, Google suggests to do so When you open it, you'll see that some basic implementation already exists. Now, you can return in the ViewController.swift and change the class of the� To sign in to the Google app with your Google Account: On your iPhone or iPad, open the Google app . Add your Google Account. To add an account for the first time: Tap Sign in. To add another account: On the top left, tap your profile image. Tap the account that's already signed in. Select the account you want to use.

Comments
  • Ok, I took your logic and put it in my Delegateapp. It works, almost :). When I run the app and I'm signed in - that's great, I see the main TabController and skip the ViewController. When I'm not logged in and run the app I see the ViewController with a sign in button. I perform the sign in process and instead of going to TabController I'm back in ViewController and I cannot proceed to the TabController since the google login button does not do anything (since I'm already logged in). How can I fix it?
  • @randomuser1 have you verified that hasAuthKeychain() returns false after you log the user out?
  • @randomuser1 Also noticed that it looks like you aren't casting the UITabBarController to your subclass.
  • yes I checked that it returns false, so that's good message. Speaking about your next comment and casting - Can you give me some example how to do it? sorry, I'm not exactly sure what you meant about that :(
  • @randomuser1 cast to your TabController, not the stock UIKit ex - if let tabBarVC = sb.instantiateViewControllerWithIdentifier("TabController") as? TabController { window!.rootViewController = tabBarVC } } else { print("user is NOT signed in") /* code to show your login VC */ let sb = UIStoryboard(name: "Main", bundle: nil) if let vc = sb.instantiateViewControllerWithIdentifier("ViewController") as? ViewController { window!.rootViewController = vc } }