Firebase Authentication の iOS 導入手順【⑦Googleアカウントログイン編】【SwiftUI】

今回は Google アカウントを利用した認証手順について解説します。

前回まで記事については下記をご参照ください。

Firebase Authentication の iOS 導入手順【⑦Googleアカウントログイン編】【SwiftUI】

(1) Sign in Method で Google ログインを許可する

先ず最初に、Firebase コンソール画面にログインし Google アカウントによるログインを許可する必要があります。

[Authentication] > [Sign-in method] からログインプロバイダの Google を有効化しましょう。

保存して、有効になっているか確認してください。

(2) GoogleSignIn を pod install する

vi コマンドで Podfile を開き、Firebase/Auth と GoogleSignIn をインストールするように設定します。

$ vi Podfile
・・・
pod 'Firebase/Auth'
pod 'GoogleSignIn'

pod install でインストールしましょう。

$ pod install

(3) URL Types の設定

Xcode の [Targets] > [Info] > [URL Types] を追加し、URL Scheme に GoogleService-Info.plist の REVERSED_CLIENT_ID を指定します

(4) GIDSignIn インスタンスの設定

ここからソースコードの方に移ります。

先ず、AppDelegatedidFinishLaunchingWithOptions 内で GIDSignIn のシングルトンインスタンスに対して FirebaseApp のクライアントIDを設定します。

import Firebase
import GoogleSignIn

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        
        GIDSignIn.sharedInstance()?.clientID = FirebaseApp.app()?.options.clientID

        return true
    }
・・・
}

(4) Google ログインボタンを作成する

Google アカウントのログインを実行するには専用のボタンである GIDSignInButton を用意する必要があります。

これは UIKit 前提のボタンとなっているため、SwiftUI で使う場合は以下のように UIViewControllerRepresentable を継承しラッピングします

※コード内の GoogleSignInViewController は後述します。

struct GoogleSignInButton: View {
    
    var body: some View {
        GoogleSignInButtonViewController()
    }
}

struct GoogleSignInButtonViewController: UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> UIViewController {
        let gidSignInButton = GIDSignInButton()
        gidSignInButton.style = .wide
        let viewController = GoogleSignInViewController()
        viewController.view.addSubview(gidSignInButton)
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        
    }
}
Google ログインボタンの表示

ボタンをタップするとブラウザが立ち上がり、Google アカウントによるログイン画面が表示されます(ただし、この時点では後述の処理が足りていないためエラーとなってしまいます)。

(5) ブラウザからのログイン結果をキャッチする

ボタンを押して立ち上がるブラウザの処理と連携するために、GIDSignIn インスタンスにデリゲートを設定する必要があります。

これは、UIViewController でなくてはいけないため、GIDSignInDelegate を継承した以下のような ViewController を作成します。

import UIKit
import GoogleSignIn
import FirebaseAuth

class GoogleSignInViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        GIDSignIn.sharedInstance()?.presentingViewController = self
        GIDSignIn.sharedInstance()?.delegate = self
    }
}

extension GoogleSignInViewController: GIDSignInDelegate {
    
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        
        if let error = error {
            print(error.localizedDescription)
            return
        }
        
        guard let auth = user.authentication else {
            return
        }
        
        let credential = GoogleAuthProvider.credential(withIDToken: auth.idToken, accessToken: auth.accessToken)
        
        Auth.auth().signIn(with: credential) { authResult, error in
            if let error = error {
                print(error.localizedDescription)
            } else {
                print("Google SignIn Success!")
            }
        }
    }
}

ブラウザ側でログイン処理が完了すると、

sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!)

がコールされます。

引数の user の情報を使って、GoogleAuthProvidercredential(認証情報)を生成し、それを引数に FirebaseAuth の signIn を実行します。

サインアウトしたい場合は Auth.auth().signOut をコールすればOKです

signOut はプロバイダの種類を問わないため、メールアドレスとパスワードの時と同じです。

do {
    try Auth.auth().signOut()
} catch let signOutError as NSError {
    print ("Error signing out: %@", signOutError)
}

以上