iOSでFirebase AuthenticationをFacebookログインでやってみる

処理の流れは以下のようになります。

- ログイン済みかチェックし、未ログインならログインボタンを表示
- ログインボタンを押下するとfacebookのログイン画面がsafariで開く。
- ログインに成功したらcredentialをFirebaseに登録。

こちらの手順を参考にしました。
[Authenticate Using Facebook Login on iOS  |  Firebase](https://firebase.google.com/docs/auth/ios/facebook-login?authuser=1)

## 準備
### Firebaseコンソールでプロジェクトを追加

[Firebase Console](https://firebase.google.com/?hl=ja)にログインしてプロジェクトを作成します。
iosアプリにFirebaseを追加します。

### Facebook for DevelopersでFacebookアプリを作成

[Facebook for Developers](https://developers.facebook.com/)にログインしてアプリを作成します。

*設定 > ベーシック*でアプリIDとapp secretが確認できるので控えておきます。

### FirebaseコンソールでFacebookログインを有効化

コンソールの*開発 > Authentication*を開きFacebookを選択します。
選択するとアプリケーションIDとアプリシークレットを入力する画面が表示されるので、先程控えたアプリケーションIDとアプリシークレットを入力します。
表示されているOAuth redirect URIを控えておきます。

### Facebook for DevelopersでFacebookログインを有効化

アプリのダッシュボードを開き、プロダクトの追加から「Facebookログイン」を追加します。
Facebookログインの設定を開き、有効なOAuthリダイレクトURIに先程Firebase consoleで控えたリダイレクトURIを入力します。

## 実装

### Podfileに必要なライブラリを追加
Firebaseの基本機能とAuth、Facebookログイン用のSDKを追加します。

```
pod 'Firebase/Core'
pod 'Firebase/Auth'
pod 'FBSDKLoginKit'
```

プロジェクトルートでコマンドを実行します。

```
$ pod install
```

### info.plistを編集
[iOS FacebookログインSDK](https://developers.facebook.com/docs/facebook-login/ios)ページの*4. info.plistを構成する*から以下のような2つのXMLをコピーしてinfo.plistの`<dict>...</dict>`に貼り付けます。

```xml
<key>CFBundleURLTypes</key>
<array>
  <dict>
  <key>CFBundleURLSchemes</key>
  <array>
    <string>XXXXXXXX</string>
  </array>
  </dict>
</array>
<key>FacebookAppID</key>
<string>XXXXXXXX</string>
<key>FacebookDisplayName</key>
<string>XXXXXXXX</string>
```
```xml
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>fbapi</string>
  <string>fb-messenger-share-api</string>
  <string>fbauth2</string>
  <string>fbshareextension</string>
</array>
```

### AppDelegate
AppDelegate.swiftを以下のように編集します。

```swift:AppDelegate.swift
import UIKit
import Firebase
import FBSDKCoreKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    func application(_ application: UIApplication,open url: URL,sourceApplication: String?,annotation: Any) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        FBSDKAppEvents.activateApp()
    }
}
```

### ViewController
ViewController.swiftを以下のように編集します。

```swift:ViewController.swift
import UIKit
import Firebase
import FBSDKCoreKit
import FBSDKLoginKit

class ViewController: UIViewController,FBSDKLoginButtonDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        // ログイン済みかチェック
        if let token = FBSDKAccessToken.current() {
            let credential = FacebookAuthProvider.credential(withAccessToken: token.tokenString)
            Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
                if error != nil {
                    // ...
                    return
                }
                // ログイン時の処理
            }
            return
        }
        // ログインボタン設置
        let fbLoginBtn = FBSDKLoginButton()
        fbLoginBtn.readPermissions = ["public_profile", "email"]
        fbLoginBtn.center = self.view.center
        fbLoginBtn.delegate = self
        self.view.addSubview(fbLoginBtn)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    // login callback
    func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
        
        if error != nil {
            print("Error")
            return
        }
        // ログイン時の処理
    }
    
    @IBAction func logoutButton(_ sender: Any) {
        let firebaseAuth = Auth.auth()
        do {
            try firebaseAuth.signOut()
        } catch let signOutError as NSError {
            print ("Error signing out: %@", signOutError)
        }
    }
    
    // Logout callback
    func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
    }
}
```

## 動作確認
アプリを起動すると、Facebookログインボタンが表示されます。
Facebookログインに成功するとFirebaseのコンソールから*開発 > Authentication > ユーザー*にユーザーが追加されます。