2021.11.10 更新:原本文章是用 Version8 ,今日新增 Version 9 的程式碼。「範例及原始碼」的檔案也新增了 Version 9 的部份。
本篇要解決的問題
最近在寫第三方登入的前端部份,因為是手刻的會員系統,在跟後端討論時,總覺得對方把東西處理的很複雜,有可能是之前自己玩的都是接 Firebase,Firebase 都把後端處理的好好的,前端直接用 SDK 裡的 function 就能取得會員資料。
之前就想把 Firebase 的第三方登入做個整理,不然每次要用都要回頭翻文件,這次趁著看 Firebase 怎麼處理第三方登入的部份時,就一併整理成這篇。
本篇主要是整理比較常用的二個第三方登入:Google、Facebook。
其他像 Github、Twitter ……等的,台灣比較少見,就之後有空再來看。
2021.04.26:今天寫完 GitHub 的方式了,請見這篇 GitHub。
之前有寫過一篇 Firebase Authentication 用帳號密碼登入的,有興趣的朋友們也可以點開來看:
用 Firebase Authentication 做一套簡易會員系統 – 電子郵件 密碼
建立 Firebase 專案、應用程式
這一步在寫電子郵件登入方式的那篇就有寫過了,這邊不再重寫,可直接點開來看:建立 Firebase 專案、應用程式
最後我們的 HTML 檔上,會引用以下的 Firebase SDK:
Google:開通 Authentication 功能
Firebase 進到專案的後台,點擊左側「Authenication」選單,接著點擊上方「Sign-in method」頁籤,會看到一排登入功能的清單,點「Google」後點擊「啟動」、「儲存」就開通了:
開通以後,頁面再往下拉,會看見「已授權網域」的列表:
這邊指的是在哪些網域下才可以使用 Firebase Auth 功能,一個白名單的概念,不在這份列表內的網域會一律報錯。
預設有一組 localhost,這是為了給我們開發時使用,功能要正式上線時記得刪除。
要新增網域,只要點擊右上角的「新增網域」:
接著填我們的網域在輸入框上,按下「新增」即可。
Google 登入
參考文件:使用帶有JavaScript的Google登錄進行身份驗證
Google 登入有二種,一種是新開一個 Popup 的小視窗,在小視窗中讓使用者登入自己的 Google 帳號;另一種是原頁整個轉到 Google 的登入頁面,登入回來後用 function 去取得使用者資料。
Popup Version 8
Popup Version 9
使用 Version 9 的 Firebase 版本,要先安裝 Firebase Package,專案開啟終端機並輸入:
npm install firebase 或 yarn add firebase
Token 是如果需要用到其它 Google API 時會要提供的。
user 就是使用者的資料,有一些是我們可以抓下來,存到資料庫中的:
user.displayName: 顯示名稱
user.email: 電子信箱
user.emailVerified: 這個電子信箱是否有驗證
user.photoURL: 大頭照的路徑
user.uid: Firebase Auth 派給這個使用者的 User ID
Firebase Authentication 後台可以看到有哪些使用者登入的清單:
Redirect Version 8
Redirect 分成二個部份,一個是當登入按鈕被點擊時,另一個是頁面載入後要主動執行的。
按鈕被點擊時執行:
const providerGoogle = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithRedirect(providerGoogle);
這一段會讓使用者轉到 Google 的登入頁面,使用者登入完後,會再回到原本的頁面,因此我們的頁面要執接觸發一段 JS 讓 Firebase 抓使用者的資料:
這段只要當使用者登入回來後才會執行,也才抓得到使用者資料。
這邊抓的使用者資料就跟 Popup 的方式一樣,不再重寫。
Redirect Version 9
按鈕被點擊時執行:
import { getAuth, signInWithRedirect, GoogleAuthProvider } from "firebase/auth"; const auth = getAuth(); const providerGoogle = new GoogleAuthProvider(); signInWithRedirect(auth, providerGoogle);
回到頁面後抓使用者資料:
Facebook:應用程式、ID、密鑰、URL
要在 Firebase 開啟 Facebook 登入功能,需要有一組 Facebook 應用程式的 ID、密鑰。
本篇建立的應用程式是示範用,本篇上線時就會刪除,因此應用程式編號、密鑰都會不存在。
進到 FACEBOOK for Developers 的頁面並登入 FB 帳號後,點擊「建立應用程式」:
工作的部份選「打造互聯體驗」:
下一個是要填寫應用程式的顯示名稱,就填一個我們看得懂在做什麼的名稱:
填完後按下「建立應用程式」,就會建立完成。
應用程式編號、密鑰、OAuth URL
應用程式建立完,進到應用程式,左側選單點擊「設定 > 基本資料」,就會看到「應用程式編號」、「應用程式密鑰」,以及一些需要填寫的欄位:
如上圖,我們可以取得應用程式的編號、密鑰,這二個記下來,等等在 Firebase 上會需要輸入。
必填欄位有三個:
- 隱私權政策網址
- 用戶資料刪除
- 類別
用戶資料刪除的網址,分為「資料刪除回呼網址、資料刪除指示網址」二個。
像本篇最後製作出的 Demo 頁,本身就可以在使用者登入後,秀出一個按鈕讓使用者自行刪除,所以可以選擇指示網址,然後貼上 Demo 頁的網址。
這三個欄位都填選完,按下儲存變更。
接著我們到 Firebase 的後台,點擊左側「Authenication」選單,接著點擊上方「Sign-in method」頁籤,會看到一排登入功能的清單,點「Facebook」後按下啟動,會看見有二個欄位要填,跟一個顯示 URL 的欄位:
「應用程式 ID」就是我們剛在 FB 後台看到的「應用程式編號」,「應用程式密鑰」就是 FB 後台的「應用程式密鑰」。
ID、密鑰填好後,我們把第三欄的 URL 給複製下來,按下儲存,再回到 FB 的後台,這次點擊左側選單的「產品 > Facebook 登入 > 設定」:
頁面上有一個「有效的 OAuth 重新導向 URI」的欄位,把我們從 Firebase 上複製的 URL 貼上去,按下儲存。
最後,FB 後台的頂部那條,有一個「調整中」的按鈕,點擊一下,FB 會確認必要的資料是否都填寫,然後按下「切換模式」,就會看見「調整中」變為「上線」:
當看見模式是上線時,這一步就大功告成,可以開始寫 code 執行登入了。
Facebook 登入
參考文件:使用JavaScript和Facebook登錄進行身份驗證
FB 登入有二種,一種是新開一個 Popup 的小視窗,在小視窗中讓使用者登入自己的 FB 帳號;另一種是原頁整個轉到 FB 的登入頁面,登入回來後用 function 去取得使用者資料。
Popup Version 8
Popup Version 9
accessToken 是如果需要用到其它 Facebook API 時會要提供的。
user 就是使用者的資料,有一些是我們可以抓下來,存到資料庫中的:
user.displayName: 顯示名稱
user.email: 電子信箱
user.emailVerified: 這個電子信箱是否有驗證
user.photoURL: 大頭照的路徑
user.uid: Firebase Auth 派給這個使用者的 User ID
要注意的是 user.email
這個值,因為使用者是可以手動改成不提供的,如果使用者改成不提供,這邊就會是 null
。
而且實測後發現,當第一次使用者改成不提供時,因為 Firabse Auth 已經派了 uid,即便後來使用者又改為提供後再登入一次,Firebase 後台上還是不會收到使用者的 email,這……算是 Bug 嗎?
Firebase Authentication 後台看到的使用者登入清單上,會看見帶有 Facebook 的標誌:
Redirect Version 8
跟用 Google 登入時一樣,FB 登入用 Redirect 方式一樣分成二部份:點擊登入按鈕時、頁面載入後主動執行。
按鈕被點擊時執行:
const providerFb = new firebase.auth.FacebookAuthProvider(); firebase.auth().signInWithRedirect(providerFb);
這一段會讓使用者轉到 Google 的登入頁面,使用者登入完後,會再回到原本的頁面,因此我們的頁面要執接觸發一段 JS 讓 Firebase 抓使用者的資料:
這段只要當使用者登入回來後才會執行,也才抓得到使用者資料。
這邊抓的使用者資料就跟 Popup 的方式一樣,不再重寫。
Redirect Version 9
按鈕被點擊時執行:
import { getAuth, signInWithRedirect, FacebookAuthProvider } from "firebase/auth"; const auth = getAuth(); const providerFb = new FacebookAuthProvider(); signInWithRedirect(auth, providerFb);
回到頁面後抓使用者資料:
登出、刪除帳號
Firebase 的第三方登入可以讓會員登出,以及刪除自己的帳號。
登出 Version 8
參考文件:https://firebase.google.com/docs/auth/web/google-signin
firebase.auth().signOut().then(() => { // 登出成功 }).catch((error) => { // 有錯誤 });
登出 Version 9
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut().then(() => { // 登出成功 }).catch((error) => { // 有錯誤 });
刪除 Version 8
參考文件:刪除用戶
var user = firebase.auth().currentUser; user.delete().then(function() { // 帳號被刪除 }).catch(function(error) { // 有錯誤 });
刪除 Version 9
import { getAuth, deleteUser } from "firebase/auth"; const auth = getAuth(); const user = auth.currentUser; deleteUser(user).then(function() { // 帳號被刪除 }).catch(function(error) { // 有錯誤 });
範例及原始檔
本篇實作的範例:
Version 8:https://letswritetw.github.io/letswrite-firebase-auth-google-fb/
Version 9:https://letswritetw.github.io/letswrite-firebase-auth-google-fb/v9.html
登入以後,頁面下方會出現「登出」、「刪除我的帳號」二個按鈕,大家記得要把自己的帳號給刪除。
因為頁面有 Google、Facebook 的二種登入方法,登出或刪除會是執行最後登入的那個第三方。比方先登了 Google,再登了 FB,那按下刪除時會刪的是 FB,記得如果二個都有登入,二個都要執行一次「刪除我的帳號」。
原始碼也整理在 Github 上:
https://github.com/letswritetw/letswrite-firebase-auth-google-fb
你好想請問如果我的facebook 和 google是相同信箱
只要用google第三方登入後 改用facebook登入 就會回傳告知這個信箱被用過
這個問題有辦法解決嗎
應該無法,因為 email 在後台是「ID」的欄位,第三方對 Firebase 來說就是提供 email 的一個媒介。
我今天在後台有找到這個可以選
好像能解決這個問題
配合的後端oauth還沒做好,還不能測試最終解果
哦,剛進後台看了一下,真的可以改變這設定。
剛改了以後試了一下,發現登入時,email 就不會是必須提供的欄位,收到的 email 都會是空值。
看文件上是寫「應用程式的登入流程就不能僅透過電子郵件地址來辨識使用者帳戶。」
意思應該就是 email 不能當唯一值了,如果我們確定要改不限 email 可重複使用,那就必須自己用別的欄位當唯一值來驗證。