Getting OAuth client ID
You will need an OAuth client ID and an iOS URL scheme to continue with the configuration in Xcode.
Head over to Google APIs Console and create a project for your app. If you have already created a project, you can also select it from the project list.
After you have created/selected a project, you also need to configure the OAuth consent screen. Follow the steps
In the OAuth consent screen information page, fill in the application name, email and then click Save and continue. This application name will be the name being shown in the Google Sign-in form when a user tries to sign in using your app.
Once finished configuring the OAuth consent screen, it is time to create the OAuth client ID.
Once you reach the OAuth client ID creation page, go ahead and select iOS as application type, fill in the name and also your sample app bundle ID and then click Create.
Click below OAuth 2.0 Client IDs and copy the OAuth client ID and iOS URL scheme you just create and keep them in somewhere easily reachable, you will need both of them in just a bit.
With that you have completed the OAuth client ID creation process, we can now head back to Xcode and proceed with the configuration.
Xcode
Before you can begin integrating your iOS app with the Google Sign-In components, you must download the dependencies and configure your Xcode project.
Install the Google Sign-In dependencies in your project
# CocoaPods pod 'GoogleSignIn' # Swift Package Manager https://github.com/google/GoogleSignIn-iOS
Google Sign-in requires a custom URL Scheme to be added to your project. To add the custom scheme, follow the steps
Next, open AppDelegate.swift
and import the GoogleSignIn
module.
import GoogleSignIn After that, update ``application(_:didFinishLaunchingWithOptions:)``. func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GIDSignIn.sharedInstance().clientID = "CID" GIDSignIn.sharedInstance().delegate = self GIDSignIn.sharedInstance()?.restorePreviousSignIn() return true }
Next, add the following AppDelegate method implementation right after application(_:didFinishLaunchingWithOptions:)
.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { var handled: Bool handled = GIDSignIn.sharedInstance().handle(url) if handled { return true } // Handle other custom URL types. // If not handled by this app, return false. return false }
Lastly, let’s conform AppDelegate to GIDSignInDelegate
and implement the sign(_:didSignInFor:withError:)
method.
extension AppDelegate: GIDSignInDelegate { func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let error = error { if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue { print("The user has not signed in before or they have since signed out.") } else { print("\(error.localizedDescription)") } return } // Post notification after user successfully sign in NotificationCenter.default.post(name: .signInGoogleCompleted, object: nil) } } extension Notification.Name { static var signInGoogleCompleted: Notification.Name { return .init(rawValue: #function) } }
UIKit
To easy AutoLayout I'm going to use SnapKit and add all the UI elements into the view controller programmatically.
import UIKit import SnapKit import GoogleSignIn class ViewController: UIViewController { var googleSignIn = GIDSignIn.sharedInstance() let statusLabel = UILabel() let signInButton: GIDSignInButton = { let v = GIDSignInButton() v.style = .wide v.addTarget(self, action: #selector(handleSignIn), for: .touchUpInside) return v }() let signOutButton: UIButton = { let v = UIButton(type: .system) v.setTitle("SignOut", for: .normal) v.addTarget(self, action: #selector(handleSignOut), for: .touchUpInside) return v }() lazy var stackView: UIStackView = { let v = UIStackView(arrangedSubviews: [statusLabel, signInButton, signOutButton]) v.axis = .vertical v.distribution = .fillEqually v.spacing = 8 v.alignment = .center return v }() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() setupView() GIDSignIn.sharedInstance()?.presentingViewController = self NotificationCenter.default.addObserver(self, selector: #selector(userDidSignInGoogle(_:)), name: .signInGoogleCompleted, object: nil) } // MARK: - Helpers private func setupView() { view.addSubview(stackView) stackView.snp.makeConstraints { make in make.center.equalToSuperview() } updateScreen() } private func updateScreen() { if let user = GIDSignIn.sharedInstance()?.currentUser { statusLabel.text = "Hello \(user.profile.givenName!)!" signInButton.isHidden = true signOutButton.isHidden = false printUser(user: user) } else { statusLabel.text = "Please sign in" signInButton.isHidden = false signOutButton.isHidden = true } } private func printUser(user: GIDGoogleUser?) { guard let user = user else { print("Uh oh. The user cancelled the Google login.") return } let userId = user.userID ?? "" print("Google User ID: \(userId)") let userIdToken = user.authentication.idToken ?? "" print("Google ID Token: \(userIdToken)") let userFirstName = user.profile.givenName ?? "" print("Google User First Name: \(userFirstName)") let userLastName = user.profile.familyName ?? "" print("Google User Last Name: \(userLastName)") let userEmail = user.profile.email ?? "" print("Google User Email: \(userEmail)") let googleProfilePicURL = user.profile.imageURL(withDimension: 150)?.absoluteString ?? "" print("Google Profile Avatar URL: \(googleProfilePicURL)") } // MARK: - Handlers @objc func handleSignIn() { GIDSignIn.sharedInstance()?.signIn() } @objc func handleSignOut() { GIDSignIn.sharedInstance()?.signOut() updateScreen() } @objc private func userDidSignInGoogle(_ notification: Notification) { updateScreen() } }