iOS

Sign In with Google

Introduction

Nowadays, it is common for applications to offer more than one type of sign-in method. Therefore, for users it is easier to sign in with an account they already have, such as a Google account or Apple ID. Furthermore, social networks (like Facebook) make available an SDK for developers to integrate a sign-in option using their social network credentials.

We start this guide by first integrating the sign-in feature provided by Google. After the user successfully signed in with their Google credential, we use the account information returned by Google to sign in a new user that will be associated with the corresponding Google account.

In this repository, we provide a simple Xcode template where you can test the different sign-in methods we are implementing. This project was already introduced in the previous guide, you can revisit it for more details about the project.

Prerequisites

To complete this quickstart, you need:

  • A recent version of Xcode.
  • An application created on Back4App.

Goal

To integrate a user sign-in feature using Google’s SDK and ParseSwift.

Step 1 - Setting up Google’s SDK

Once we have the Xcode project linked to the Back4App application, we proceed to add Google’s SDK which will allow us to implement the sign-in flow. For this example, we use the Swift Package Manager (SPM) to add Google Sign-in dependencies. In the Xcode project, go to File>Add packages… and in the search bar, look for https://github.com/google/GoogleSignIn-iOS.

Once the GoogleSignIn-iOS option appears in the results, click on the Add Package button.

Next, go to the dashboard of your Google developer account and create a new project.

Once the project has been created, the next step is to create an OAuth client id. In the Google cloud console select your new project and go to the credentials page. This can be found from the left menu:

During this process, you may need to set up the OAuth consent screen that will appear in the sign-in with Google form and fill in the corresponding requirements accordingly.

To conclude this step, we have to add in the app’s URL schemes the URL generated during the creation of the OAuth client id. Go to the project configuration and select the main app target. Then go to the info section and add the corresponding URL scheme from your Google project.

Step 2 - Using Google Sign in with ParseSwift

With GoogleSignIn successfully integrated into your Xcode project, we proceed to implement the sign in with Google feature. In the project example, the LogInController is in charge of handling and displaying the different sign-in options. We then set up the signInWithAppleButton action in this controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// LogInController.swift file
import GoogleSignIn
...

class LogInController: UIViewController {
  ...

  private let signInWithGoogleButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(UIImage(named: "googleIcon"), for: .normal)
    button.imageView?.contentMode = .scaleAspectFit
    return button
  }()

  override func viewDidLoad() {
    super.viewDidLoad()
    // ...
    // Layout configuration
    // ...

    signInWithGoogleButton.addTarget(self, action: #selector(handleSignInWithGoogle), for: .touchUpInside)
  }
}

// MARK: - Sign in with Google section
extension LogInController {
  @objc fileprivate func handleSignInWithGoogle() {
    // TODO: Here we will implement the sign-in procedure
  }
}

In order to show the sign-in form from Google, the GoogleSignIn SDK allows us to set up and present it via the signIn(with:presenting:callback) method from the GIDSignIn class. Additionally, we have to pass a GIDConfiguration object instantiated using the client id created in the previous step, then presenting view controller, and a callback closure. In the callback closure, Google returns the user credentials (embedded in a GIDGoogleUser object) or an error if the authentication failed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// MARK: - Sign in with Google section
extension LogInController {
  @objc fileprivate func handleSignInWithGoogle() {        
    let signInConfig = GIDConfiguration(clientID: "MY_CLIENT_ID") // See https://developers.google.com/identity/sign-in/ios/sign-in for more details
        
    // Method provided by the GoogleSignIn framework. See https://developers.google.com/identity/sign-in/ios/sign-in for more details
    GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { [weak self] googleUser, error in
      if let error = error {
        self?.showMessage(title: "Error", message: error.localizedDescription)
        return
      }
            
      // After Google returns a successful sign in, we get the users id and idToken
      guard let googleUser = googleUser,
            let userId = googleUser.userID,
            let idToken = googleUser.authentication.idToken
      else { fatalError("This should never happen!?") }
            
      // TODO: Sign in the user in your Back4App application.
    }
  }
}

We then take these credentials and use them to sign in to the user on the Back4App platform. The object representing the user is the following struct (see the previous guide for more details):

1
2
3
4
5
6
7
8
9
10
11
12
import ParseSwift

struct User: ParseUser {
  ...
  
  var username: String?
  var email: String?
  var emailVerified: Bool?
  var password: String?
  
  var age: Int?
}

Therefore, the credential returned by Google contains an idToken and the user’s id that will be used to complete the sign-in process. More precisely, we instantiate a ParseGoogle<User> object and call the login(id:idToken:completion) method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// MARK: - Sign in with Google section
extension LogInController {
  @objc fileprivate func handleSignInWithGoogle() {
    GIDSignIn.sharedInstance.signOut() // This should be called when the user logs out from your app. For login testing purposes, we are calling it each time the user taps on the 'signInWithGoogleButton' button.
        
    let signInConfig = GIDConfiguration(clientID: "MY_CLIENT_ID") // See https://developers.google.com/identity/sign-in/ios/sign-in for more details
        
    // Method provided by the GoogleSignIn framework. See https://developers.google.com/identity/sign-in/ios/sign-in for more details
    GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { [weak self] googleUser, error in
      if let error = error {
        self?.showMessage(title: "Error", message: error.localizedDescription)
        return
      }
            
      // After Google returns a successful sign in, we get the users id and idToken
      guard let googleUser = googleUser,
            let userId = googleUser.userID,
            let idToken = googleUser.authentication.idToken
      else { fatalError("This should never happen!?") }
            
      // With the user information returned by Google, you need to sign in the user on your Back4App application
      User.google.login(id: userId, idToken: idToken) { result in
        // Returns the User object asociated to the GIDGoogleUser object returned by Google
        switch result {
          case .success(let user):
          // After the login succeeded, we send the user to the home screen
          // Additionally, you can complete the user information with the data provided by Google
          let homeController = HomeController()
          homeController.user = user

          self?.navigationController?.pushViewController(homeController, animated: true)
          case .failure(let error):
          // Handle the error if the login process failed
          self?.showMessage(title: "Failed to sign in", message: error.message)
        }
      }
    }
  }
}

Step 3 - Verifying user sign in and session creation

To make sure, that the Google sign-in worked, you can look at your Back4App application dashboard and see the new User, containing the Google authData parameters.

Back4App

You can also verify that a valid session was created in the dashboard, containing a pointer to the corresponding User object.

Back4App

Step 4 - Linking an existing User to a Google account

In case your iOS App requires you to associate a Google account with an existing user in your Back4App platform, the ParseGoogle<User> object implements the method link(id:completion:) where you pass the id of the Google account to be linked:

1
2
3
4
5
6
7
8
9
10
let googleUserId: String // The id of the Google account to link to

User.google.link(id: googleUserId) { [weak self] result in
  switch result {
  case .success(let user):
    // Linking succeeded, user object now is linked to the corresponding Google account
  case .failure(let error):
    // Linking failed, handle the error
  }
}

Step 5 - Signing out

The sign-out process does not vary from the standard way of calling the User.signout() method (detailed in previous guides). However, when a user signs in with a Google account, for consistency, you should sign out the current Google user as well. We can accomplish this by calling the following method alongside User.signout().

1
GIDSignIn.sharedInstance.signOut()

In order to verify if the current user has a linked Google account, you can check it by looking at the User.current?.authData dictionary.

Step 6 - Run the app

You can go to this repository and download the example project. Before running the project, make sure you set up the provisioning profiles with the ones associated with your developer account.

Conclusion

At the end of this guide, you learned how to sign in or link existing Back4App users on iOS using sign in with Google. In the next guide, we will continue with a different sign-in method.