Swift4.2でFirebase Auth + Facebook Loginを実装する

iOSアプリケーションにおいて、Firebase Auth+Facebook Loginでユーザ認証を実装する。
公式ドキュメントでSwift4の情報がまだまだ少なく嵌ったため、備忘の為の記事です。

また、Githubへソースを上げているので、参考にしてください。
https://github.com/w2-yamaguchi/firebaseAuthTest

なお、Swift3のサンプルは以下に記事を書いています。参考になれば幸いです。
https://qiita.com/w2-yamaguchi/items/6aabc18759e863a87d9f

# 環境
* Xcode10.1
* Swift4.2
* Firebase
* Facebook SDK

# 手順
## 1. Firebaseのプロジェクト作成、FacebookのMyApps作成
<< 記載予定 >>
一応、以下の公式ドキュメントが参考になります。
https://firebase.google.com/docs/auth/ios/facebook-login?hl=ja
https://developers.facebook.com/docs/facebook-login/ios

## 2. Xcodeプロジェクトへ各SDKを導入
CocoaPodsでSDKを導入します。

```text:Podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'firebaseAuthTest' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for firebaseAuthTest
  pod 'Firebase/Core'
  pod 'Firebase/Auth'
  pod 'FacebookCore'
  pod 'FacebookLogin'
  pod 'FacebookShare'

end
```

導入されたSDKのバージョンは以下を参照してください。

```sh
$ pod install
Analyzing dependencies
Downloading dependencies
Installing Bolts (1.9.0)
Installing FBSDKCoreKit (4.40.0)
Installing FBSDKLoginKit (4.40.0)
Installing FBSDKShareKit (4.40.0)
Installing FacebookCore (0.5.0)
Installing FacebookLogin (0.5.0)
Installing FacebookShare (0.5.0)
Installing Firebase (5.16.0)
Installing FirebaseAnalytics (5.5.0)
Installing FirebaseAuth (5.3.0)
Installing FirebaseAuthInterop (1.0.0)
Installing FirebaseCore (5.2.0)
Installing FirebaseInstanceID (3.4.0)
Installing GTMSessionFetcher (1.2.1)
Installing GoogleAppMeasurement (5.5.0)
Installing GoogleUtilities (5.3.7)
Installing nanopb (0.3.901)
Generating Pods project
Integrating client project
```

## 3.実装
ソースコード
https://github.com/w2-yamaguchi/firebaseAuthTest

### Info.plist
```xml:Info.plist
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>fb*****</string>
            </array>
        </dict>
    </array>
    <key>FacebookAppID</key>
    <string>*****</string>
    <key>FacebookDisplayName</key>
    <string>firebaseAuthTest</string>
```

### AppDelegate.swift
```swift:AppDelegate.swift
import Firebase
import FacebookCore

====略

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        // MARK: - Firebase
        FirebaseApp.configure()

        // MARK: - Facebook
        SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)

        return true
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

        // MARK: - Facebook
        AppEventsLogger.activate(application)
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // MARK: - Facebook
        return SDKApplicationDelegate.shared.application(app, open: url, options: options)
    }
```

### ViewController.swift
```swift:ViewController.swift
import UIKit
import FirebaseAuth
import FacebookLogin

class ViewController: UIViewController, LoginButtonDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        let loginButton = LoginButton(readPermissions: [ .publicProfile, .email ])
        loginButton.center = view.center
        loginButton.delegate = self
        
        view.addSubview(loginButton)
    }
    
    func loginButtonDidCompleteLogin(_ loginButton: LoginButton, result: LoginResult) {
        switch result {
        case .failed(let error):
            print(error)
        case .cancelled:
            print("Facebook: User cancelled login.")
        case .success(_, _, let accessToken):
            print("Facebook: User is logged in!")
            let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.authenticationToken)
            firebaseSignIn(credential: credential)
        }
    }
    
    func loginButtonDidLogOut(_ loginButton: LoginButton) {
        firebaseSignOut()
    }
    
    func firebaseSignIn(credential: AuthCredential) {
        Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
            if let e = error {
                print(e.localizedDescription)
                return
            }
            print("Firebase: User is signed in!")
        }
    }
    
    func firebaseSignOut() {
        do {
            try Auth.auth().signOut()
            print("Firebase: User is signed out.")
        } catch let error as NSError {
            print ("Firebase: Error signing out: %@", error)
        }
    }

}

```

これで完了です！！