不久前,James寫了一篇教程告訴讀者如何利用Firebase建立登入和註冊功能,現在開發人員常會使用一些聯邦式(Federated Identity)身份管理憑證,如Google登入和Facebook登入,讓用戶得以使用自己的Facebook帳戶註冊應用程序。這篇文章中,我們將學習如何使用Firebase身份驗證並且整合Facebook登入。
在進入實作內文前,你可能有一個問題。為什麼我們需要Firebase身份驗證?為什麼不直接使用Facebook SDK來實現用戶身份驗證?
即使你要使用Firebase身份驗證,不代表你不需要Facebook SDK,你仍舊需要將它安裝在Xcode專案中。儘管如此,在實現Firebase身份驗證時,大多數時間都是使用你相當熟悉的Firebase SDK。這裡舉一個例子,這是用於在登入後檢索用戶顯示名稱的程式碼:
if let currentUser = FIRAuth.auth()?.currentUser { nameLabel.text = currentUser.displayName }
如果你已經閱讀了前一章,應該會非常熟悉上面這段程式碼。現在讓我問你,如何檢索用戶的Facebook登入名稱?可能你會通過Facebook SDK文檔來尋找相應的API。
讓我告訴你,如果使用Firebase身份驗證,並且整合Facebook登入功能,可以使用相同的Firebase API(如上所示)從他/她的Facebook配置文件檢索用戶的名稱,聽起來不錯吧?
這是使用Firebase驗證與其他安全驗證服務配對的優點之一。而且,開發者可以在同一Firebase控制台中管理所有用戶(無論他們是使用電子郵件,Facebook還是Google登入)。
現在讓我們開始來看接下來的實作內容,實作可分為三個部分,以下是我們需要做的:
* 配置你的Facebook應用程式 – 要使用Facebook登入,需要在其開發者網站上創建一個新的應用程序,並完成一些配置,如應用程式ID和密碼。
* 在Firebase中設置Facebook登入 – 因為我們將使用Firebase進行Facebook登入,所以需要在Firebase控制台中設置你的應用程式。
* 將Firebase和Facebook SDK整合到Xcode項目中 – 完成所有配置後,最後一步是藉由Facebook和Firebase SDK透過程式碼實現Facebook登入。
它看起來很複雜,其實程式碼部分是相當簡單,僅然如此,它仍需要一些時間來做配置和專案設定。
Okay!讓我們開始吧。
The Demo Project
這個範例相當簡單,初始畫面有顯示兩個按鈕:使用Facebook *登入和使用Google*登入,我們將在本教程中實現Facebook登入按鈕,而Google登入按鈕讓讀者自行練習。
為了幫助讀者專注於學習Facebook登入,你可以下載初始項目,與本文內容一起進行練習。 當你下載初始項目,請打開FirebaseDemo.xcworkspace
並將com.appcoda.FirebaseDemoLogin
的bundle identifier更改為你自己的bundle identifier。這很重要,因為它必須是唯一的。
登入過程與電子郵件地址非常相似。當用戶第一次點擊Sign in with Facebook按鈕,應用程序為用戶打開登入畫面,登入畫面由Facebook提供,並且用戶需要使用他/她的Facebook帳戶登入。此外,用戶必須授予我們的應用程式權限,才能擷取他/她的電子郵件地址和公開個人資料(例如顯示名稱)。
如果用戶有安裝Facebook,應用程序將切換到Facebook以授予權限。這是用戶首次使用Facebook登入應用程序的情況,Facebook通常會緩存用戶的login資訊,所以用戶下一次使用將會自動登入。
建立Firebase應用程式
要整合Facebook登入與Firebase,第一件事是創建一個Firebase應用程式,請先前往[https://firebase.google.com](https://firebase.google.com),然後進入到控制台。 接著,添加一個新項目並將其命名為任何您想要的名稱。
當Firebase替你創建了新項目後,它將帶你到Overview頁面,在此選擇iOS平台,然後按照畫面上的步驟填寫你的bundle ID,Firebase將生成一個名為GoogleService-Info.plist
的文件。 下載它並將其添加到Xcode項目。
您可以跳過與Firebase SDK安裝相關的過程,因為初始專案已經將它包含進去了,只需跳到最後一步即可完成應用配置。
設置新的Facebook應用程式
如前所述,你將必須經歷幾個配置過程,下一步是設置一個新的Facebook應用程序。轉到[Facebook for Developers](https://developers.facebook.com/)網站,使用你的Facebook帳戶登錄。在我的應用程式的下拉式選單中,選擇[Add a new app]。系統會提示你為應用程式設定顯示名稱和類別。我把名字設置為NorthernLights
,並選擇photo
類別。
下一步,點擊Create App ID
進入到下個步驟,接著將被帶到一個dashboard,你可以在此配置Facebook登入。
現在請選擇+Add Product
,然後單擊Facebook Login旁邊的Get Started
選項。選擇iOS
後Facebook將指導開發者完成整合過程,你可以忽略Facebook SDK安裝的說明,我們將使用CocoaPods來安裝它。只需點擊繼續即可繼續執行下一步,同樣的我們也跳過第二步。在配置的第三個步驟中,你需要提供專案的bundle ID,將其設置為之前配置的bundle ID,然後單擊Save
保存更改。
就這樣,你可以跳過剩餘的過程。如果你要驗證bundle ID設置工作,請點擊側邊菜單中的Settings,應該會看到一個iOS區塊顯示bundle ID的資訊。
在畫面設置中,應該會找到你的App ID和密碼。在預設情況下,密碼*會被隱蔽起來,你可以單擊顯示按鈕來檢視它,我們需要這兩個訊息來進行Firebase配置。
在Firebase中配置Facebook Login
現在回到[Firebase控制台](https://console.firebase.google.com)並選擇你創建的應用程序(在這裡,我使用Northern Lights),在側邊menu中,選擇Authentication,然後選擇Sign-in Method。
由於我們現在正在實現Facebook登入,請單擊Facebook並將開關翻轉到ON。你必須在這裡填寫兩個欄位:App ID和App密碼,這些是稍早在Facebook應用程式設定欄位中顯示的值,請相應地填入它們,並點擊Save
保存更改。
你可能會注意到OAuth redirect URI,Google API使用OAuth 2.0協議進行身份驗證和授權。在用戶使用他/她的Facebook帳戶登錄並授予訪問權限後,Facebook將通過回調URL通知Firebase。在這裡,OAuth redirect URI是URL。
你必須複製這個URI並將其添加到你的Facebook應用程式配置中,現在回到你的Facebook應用程序。在Facebook登入側邊選單中,選擇Settings。請確保將之前複製的URI貼到Valid OAuth redirect URIs欄位中。點擊Save Changes保存設置。
很好!你已完成了Facebook應用程式和Firebase的配置。
設定專案內Firebase與Facebook的SDK
你將需要Firebase和Facebook的SDK,安裝這兩個SDK最簡單的方法是使用CocoaPods,要將SDK添加到項目,請按如下所示編輯Podfile:
# Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target 'FirebaseDemo' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for FirebaseDemo pod 'Firebase/Core' pod 'Firebase/Auth' # Pods for Facebook pod 'Bolts' pod 'FBSDKCoreKit' pod 'FBSDKLoginKit' end
更改後,打開終端機並前往這個專案的文件夾,然後輸入以下命令安裝pod(請確保在執行命令之前關閉Xcode項目):
pod install
如果一切都很順利的進行,CocoaPods將會下載你指定的SDK,並且將它們安裝至Xcode的專案中。
配置Xcode專案
在我們深入Swift程式碼之前還有一個配置作業。請打開FirebaseDemo.xcworkspace
。在專案導覽器(Project Navigator)中,右鍵單擊Info.plist
文件,並選擇Open as *> *Source code。它將會以文本格式打開檔案,這實際上是一個XML文件。
在</dict>
標記之前插入以下XML程式碼片段:
CFBundleURLTypes CFBundleURLSchemes fb564148470450124 FacebookAppID 564148470450124 FacebookDisplayName Northern Lights LSApplicationQueriesSchemes fbapi fb-messenger-api fbauth2 fbshareextension
上面程式碼是我自己的設定內容,你的應該會與我的不太一樣,請進行以下更改:
- 將App ID(
564148470450124
)更改為你自己的ID,請在Facebook應用程式的Dashboard中找尋此ID。 - 將
fb564148470450124
更改為你自己的URL scheme. 將其替換為fb{你的App ID}
。 - 將應用程式的顯示名稱(ex:Northern Lights)更改為你自己設定的名稱。
Facebook API將讀取Info.plist中的設定內容,藉此連接你的Facebook應用程式和管理Facebook登入,開發人員必須確保App ID與先前創建的ID相匹配。
LSApplicationQueriesSchemes
用來指定應用程式中UIApplication
類別的canOpenURL:
方法得以使用的URL schemes。如果使用者安裝了官方Facebook應用程式,則可以切換到該應用程序以進行登入,在這種情況下,需要在這個key值中宣告所需的URL schemes,以便Facebook可以正確執行應用程序切換。
開始進入Swift程式碼之中吧!
最後,在完成所有繁瑣的配置後,是時候開始探討Swift程式碼的部分了。現在打開AppDelegate.swift
並添加以下import語句:
import Firebase import FBSDKCoreKit
在application(_:didFinishLaunchingWithOptions:)
函式中,請加入兩行程式碼來初始化Firebase並配置Facebook Login:
FIRApp.configure() FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
在同一個class當中,請添加下面的函式:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let handled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options) return handled }
上面的程式碼是用來做什麼的呢?FBSDKApplicationDelegate
被設定用於顯示Facebook登入(例如切換到本地Facebook app)或Facebook對話框(類似於Facebook的web介面)的處理結果。為了在application(_:didFinishLaunchingWithOptions:)
方法中正確使用Facebook SDK,需要調用application
方法。
就像前面說的,Facebook登入過程可能會發生這些情況:
- 使用者點擊Facebook登入按鈕。
- 假設使用者安裝了本地的Facebook app,應用程序將切換到Facebook app,以請求用戶的權限。
- 在獲得使用者的批准後,Facebook app將切換回我們的應用程式,並且傳遞用戶的憑證,接著繼續登入動作。
當從Facebook app切換回我們的應用程式時,將調用application(_:open:options:)
方法,所以我們必須實現該方法來處理Facebook登入,為了正確處理登入動作,Facebook需要調用FBSDKApplicationDelegate
的application
方法:
FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options)
現在打開WelcomeViewController.swift
,這是歡迎頁面的view controller,用來顯示Facebook登入按鈕,在WelcomeViewController
的class當中,首先添加幾個import語句以導入所需的SDK:
import FBSDKLoginKit import Firebase
然後添加一個處理Facebook登入的操作方法:
@IBAction func facebookLogin(sender: UIButton) { let fbLoginManager = FBSDKLoginManager() fbLoginManager.logIn(withReadPermissions: ["public_profile", "email"], from: self) { (result, error) in if let error = error { print("Failed to login: \(error.localizedDescription)") return } guard let accessToken = FBSDKAccessToken.current() else { print("Failed to get access token") return } let credential = FIRFacebookAuthProvider.credential(withAccessToken: accessToken.tokenString) // Perform login by calling Firebase APIs FIRAuth.auth()?.signIn(with: credential, completion: { (user, error) in if let error = error { print("Login error: \(error.localizedDescription)") let alertController = UIAlertController(title: "Login Error", message: error.localizedDescription, preferredStyle: .alert) let okayAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) alertController.addAction(okayAction) self.present(alertController, animated: true, completion: nil) return } // Present the main view if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "MainView") { UIApplication.shared.keyWindow?.rootViewController = viewController self.dismiss(animated: true, completion: nil) } }) } }
如果讀者已經閱讀了我們的[Firebase教程](https://www.appcoda.com.tw/firebase-login-signup/),除了與FBSDKLoginManager
相關的程式碼,它非常類似於我們在實現電子郵件/密碼認證時使用的code,FBSDKLoginManager
類別提供了記錄用戶進出的方法。在實作Login功能時,你可以調用logIn
方法,並指定要請求的讀取權限。由於我們需要用戶的電子郵件地址和顯示名稱,因此將要求用戶授權public_profile
和email
的讀取權限。
在用戶登入Facebook後,無論他/她是否授予我們應用程式權限,都將會調用完整的處理程序。這裡我們先檢查是否有任何錯誤。如果沒有,我們繼續擷取用戶的access token,並通過調用將其轉換為Firebase憑證:
FIRFacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
其餘的程式碼你應該非常熟悉,我們使用Facebook憑證調用FIRAuth
的signIn
方法,如果發生任何錯誤,我們彈出一個錯誤對話框,否則,我們顯示主頁面並關閉當前視圖控制器(view controller)。
現在請切換到Main.storyboard
,並選擇Welcome View Controller Scene,接著按住Control鍵,將Sign In With Facebook按鈕拖動到Dock的視圖控制器圖標,釋放按鍵並在彈出選單中選擇facebookLoginWithSender:
連接操作方法。
設定測試帳戶
現在到了測試這個應用程式的時候了,如果妳點擊Sign In with Facebook按鈕,應該要看到Facebook的登入畫面。但是你之前配置的Facebook應用程式仍處於開發模式,如果妳使用自己的Facebook帳戶登入應用程式,將會看到錯誤:
App Not Setup: This app is still in development mode, and you don't have access to it. Switch to a registered test user or ask an app admin for permissions.
現在,你有兩個選擇來測試這個應用程式:
- 將你的Facebook app切換到production模式 – 可以在開發人員信息中心將Facebook app從development模式更改為production模式。
- 為測試目的創建測試用戶(或多個測試帳戶) – Facebook允許開發人員創建一個測試帳戶,以便在Facebook app處於development模式時執行測試。
在應用程式處於開發階段,尤其是當涉及到身份驗證時,使用一般帳戶執行所有測試是一個不好的習慣。因此,我們將優先參考第二個選項。
現在回到Facebook開發人員信息中心(Facebook Developer dashboard)並選擇Northern Lights。在側邊選單中,選擇Roles > Test Users。
在這裡您可以點擊Add
按鈕添加一個新的測試用戶。在彈出的選單中,將測試用戶數設置為1
,然後點擊Create Test Users
按鈕。 然後,Facebook將生成一個具有隨機名稱和電子郵件地址的測試用戶。點擊新測試用戶旁邊的Edit
按鈕,然後選擇Change the name or password for this test user以修改其密碼。
測試Facebook Login
很好!你現在可以準備來測試這個app了,請運行這個應用程式,當它啟動後點選Sign In with Facebook,並且使用剛剛創建的測試帳戶登錄,如果一切順利,你應該能夠前進到主頁面。
Facebook將會緩存你的登入狀態。因此,下次不再需要使用測試帳戶(或Facebook帳戶)去登入這個應用程式。
登出和使用者顯示名稱
如何登出和設定使用者檔案呢?我們需要從Facebook SDK使用指定的API嗎?你可以使用相同的程式碼片段(Code Snippet)從用戶的Facebook配置文件擷取顯示名稱。
if let currentUser = FIRAuth.auth()?.currentUser { nameLabel.text = currentUser.displayName }
Firebase相當的聰明,它可以根據登入方法(無論是來自Facebook還是使用電子郵件/密碼)確定適當的顯示名稱。
對於登出作業,我們可以使用相同的API來實現使用者的登出動作。
FIRAuth.auth()?.signOut()
以上可以看到Firebase的威力。開發者只需要調用相同的API,而Firebase將會替你處理其餘繁重的工作。
總結
在本文中,我向讀者介紹如何使用Firebase去整合Facebook Login,這裡故意忽略Google登入的功能實作,請嘗試參考Google登入文件,看看你是否能替這個app完成Google登入啟用程序。
以供參考,你可以在GitHub下載完成專案。
FB : https://www.facebook.com/yishen.chen.54
Twitter : https://twitter.com/YeEeEsS