Firebase側の設定
ログイン方法
> Google
を有効にしておく。
プロジェクトの公開名は認証画面で表示されるアプリ名となる。
アプリの基本設定
podのインストール
pod 'Firebase' pod 'Firebase/Auth' pod 'GoogleSignIn'
$ pod install $ open FirebaseChat.xcworkspace
GoogleService-Info.plistの設置
FirebaseからダウンロードしたGoogleService-Info.plistをアプリケーションフォルダに設置する。
仮に紛失した場合等は、プロジェクトの設定より再度DLできる。
URL Schemeの設
GoogleService-Info.plistのREVERSED_CLIENT_ID
に設定されているcom.google〜
から始まる値をURL Typesに設定する。
プロジェクトファイルから、TARGETS
> info
タブを選択
下段にあるURL TypesのURL SchemesにREVERSED_CLIENT_IDを入力する。
AppDelegateの設定
import GoogleSignIn import Firebase
Google認証からのURL open時の処理を記述
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let handle = GIDSignIn.sharedInstance()?.handle(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplication.OpenURLOptionsKey.annotation]) return handle! }
Firebase SDKの初期化。didFinishLaunchingWithOptionsで書くのが慣例みたい。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. FirebaseApp.configure() GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID return true }
ログインを行うViewControllerでの記述
import Firebase import GoogleSignIn
Googleログインボタンの設置
Googleログインボタンの設置。GoogleSignInパッケージの中にGIDSignInButtonというViewが入っている。
func createGoogleSigninButton(){ let googleButton = GIDSignInButton () googleButton.frame = CGRect(x: 20, y: self.view.frame.height/2-30, width: self.view.frame.width-40, height: 60) self.view.addSubview(googleButton) }
delegateの記述
GIDSignInDelegate, GIDSignInUIDelegateの実装をGIDSignInに渡す必要がある。公式ではGIDSignInDelegate
はAppDelegateで実装を記述していたが、ログインを行うViewControllerで記述しても問題がなかった。
override func viewDidLoad() { super.viewDidLoad() GIDSignIn.sharedInstance()?.delegate = self GIDSignIn.sharedInstance()?.uiDelegate = self createGoogleSigninButton() }
認証結果コールバックの記述
extension LoginViewController: GIDSignInDelegate, GIDSignInUIDelegate{ func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let error = error { print(error.localizedDescription) return } guard let authentication = user.authentication else { return } //credentialはFirebase登録/ログイン時に必要 let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken) //Firebase Baas側に認証(初回時はレコードを作成) Auth.auth().signIn(with: credential) { (authResult, error) in } //ユーザ情報へのアクセス Auth.auth().addStateDidChangeListener { (auth, user) in if let currentUser = auth.currentUser{ print(currentUser.uid) print(currentUser.displayName) print(currentUser.email) print(currentUser.photoURL) //アドレス確認メールの送信 Auth.auth().currentUser?.sendEmailVerification { (error) in } } } } }
ユーザ情報へのアクセスはGoogleの認証結果、signInやuserからでもアクセスできるが、mBaasのデータを参照したほうがお行儀がいいと思う。
流れとしては、
- GoogleのOAuthプロバイダで認証
- credentialでFirebaseの認証を取得。初回時はユーザデータの作成。この時、ユーザのprofileデータもFirebase側に作成される。
- 認証を得たFirebaseオブジェクトでユーザ情報を取得
Firebase Authenticationのサイレントログイン
GIDSignIn.sharedInstance().signIn()
delegateを設定する前に呼ぶとエラーになる。
override func viewDidLoad() { super.viewDidLoad() GIDSignIn.sharedInstance().signIn() //error GIDSignIn.sharedInstance()?.delegate = self GIDSignIn.sharedInstance()?.uiDelegate = self createGoogleSigninButton() }
Firebase Authenticationのログアウト
try? Auth.auth().signOut()
Googleログインボタンの表示制御
ログイン状態によってボタンの表示・非表示を行う場合は以下のようにすればよい。
override func viewDidLoad() { super.viewDidLoad() GIDSignIn.sharedInstance()?.delegate = self GIDSignIn.sharedInstance()?.uiDelegate = self Auth.auth().addStateDidChangeListener { (auth, user) in if auth.currentUser == nil{ self.createGoogleSigninButton() }else{ print(auth.currentUser?.uid) print(auth.currentUser?.displayName) } } }