使用 Firebase 的 Chrome 擴充功能中的 Google 驗證

我們寫本指南是因為 Google 的官方指南缺少一些重要步驟,我們在下面連結了:
在 Chrome 擴充功能中使用 Firebase 進行驗證
這適用於任何作業系統。出於本指南的目的,我們將使用 Mac OS
先決條件
- Google瀏覽器
- Google 帳號
- Chrome 網路應用商店開發者帳戶(一次性費用 5 美元)
- 已安裝 Node.js 和 npm
第 1 步:建立專案結構
a) 為您的專案建立一個新目錄:
mkdir firebase-chrome-auth cd firebase-chrome-auth
b) 建立兩個子目錄:
mkdir chrome-extension mkdir firebase-project
第 2 步:設定 Firebase 項目
a) 前往 Firebase 控制台。
b)點選「新增項目」並依照步驟建立一個新項目。
c) 建立後,按一下「Web」將 Web 應用程式新增至您的專案。
d) 使用暱稱註冊您的應用程式(例如「Chrome 擴充功能驗證」)。
e) 複製 Firebase 配置物件。稍後你會需要這個。
const firebaseConfig = {
apiKey: "example",
authDomain: "example.firebaseapp.com",
projectId: "example",
storageBucket: "example",
messagingSenderId: "example",
appId: "example"
};
f) 導航到 firebase-project 目錄
cd firebase-project
g) 初始化一個新的 npm 項目
npm init -y
h) 安裝 Firebase:
npm 安裝 firebase
i) 在 firebase-project/index.html
中建立一個 index.html 文件
<!DOCTYPE html> <html> <head> <title>Firebase Auth for Chrome Extension</title> </head> <body> <h1>Firebase Auth for Chrome Extension</h1> <script type="module" src="signInWithPopup.js"></script> </body> </html>
j) 在 firebase-project/signInWithPopup.js
中建立一個signInWithPopup.js 文件
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
const firebaseConfig = {
// Your web app's Firebase configuration
// Replace with the config you copied from Firebase Console
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
// This gives you a reference to the parent frame, i.e. the offscreen document.
const PARENT_FRAME = document.location.ancestorOrigins[0];
const PROVIDER = new GoogleAuthProvider();
function sendResponse(result) {
window.parent.postMessage(JSON.stringify(result), PARENT_FRAME);
}
window.addEventListener('message', function({data}) {
if (data.initAuth) {
signInWithPopup(auth, PROVIDER)
.then(sendResponse)
.catch(sendResponse);
}
});
k) 部署 Firebase 專案
npm install -g firebase-tools firebase login firebase init hosting firebase deploy
請注意部署後提供的託管 URL。 Chrome 擴充功能需要它。
第 3 步:設定 Chrome 擴充功能
a) 導覽至 chrome-extension 目錄
cd ../chrome-extension
b) 在chrome-extension/manifest.json
中建立一個manifest.json文件
{
"manifest_version": 3,
"name": "Firebase Auth Extension",
"version": "1.0",
"description": "Chrome extension with Firebase Authentication",
"permissions": [
"identity",
"storage",
"offscreen"
],
"host_permissions": [
"https://*.firebaseapp.com/*"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_popup": "popup.html"
},
"web_accessible_resources": [
{
"resources": ["offscreen.html"],
"matches": ["<all_urls>"]
}
],
"oauth2": {
"client_id": "YOUR-ID.apps.googleusercontent.com",
"scopes": [
"openid",
"email",
"profile"
]
},
"key": "-----BEGIN PUBLIC KEY-----\nYOURPUBLICKEY\n-----END PUBLIC KEY-----"
}
c) 在 chrome-extension/popup.html
中建立 popup.html 文件
<!DOCTYPE html>
<html>
<head>
<title>Firebase Auth Extension</title>
</head>
<body>
<h1>Firebase Auth Extension</h1>
<div id="userInfo"></div>
<button id="signInButton">Sign In</button>
<button id="signOutButton" style="display:none;">Sign Out</button>
<script src="popup.js"></script>
</body>
</html>
d) 在 chrome-extension/popup.js
中建立 popup.js 文件
document.addEventListener('DOMContentLoaded', function() {
const signInButton = document.getElementById('signInButton');
const signOutButton = document.getElementById('signOutButton');
const userInfo = document.getElementById('userInfo');
function updateUI(user) {
if (user) {
userInfo.textContent = `Signed in as: ${user.email}`;
signInButton.style.display = 'none';
signOutButton.style.display = 'block';
} else {
userInfo.textContent = 'Not signed in';
signInButton.style.display = 'block';
signOutButton.style.display = 'none';
}
}
chrome.storage.local.get(['user'], function(result) {
updateUI(result.user);
});
signInButton.addEventListener('click', function() {
chrome.runtime.sendMessage({action: 'signIn'}, function(response) {
if (response.user) {
updateUI(response.user);
}
});
});
signOutButton.addEventListener('click', function() {
chrome.runtime.sendMessage({action: 'signOut'}, function() {
updateUI(null);
});
});
});
e) 在chrome-extension/background.js
中建立background.js文件
const OFFSCREEN_DOCUMENT_PATH = 'offscreen.html';
const FIREBASE_HOSTING_URL = 'https://your-project-id.web.app'; // Replace with your Firebase hosting URL
let creatingOffscreenDocument;
async function hasOffscreenDocument() {
const matchedClients = await clients.matchAll();
return matchedClients.some((client) => client.url.endsWith(OFFSCREEN_DOCUMENT_PATH));
}
async function setupOffscreenDocument() {
if (await hasOffscreenDocument()) return;
if (creatingOffscreenDocument) {
await creatingOffscreenDocument;
} else {
creatingOffscreenDocument = chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.DOM_SCRAPING],
justification: 'Firebase Authentication'
});
await creatingOffscreenDocument;
creatingOffscreenDocument = null;
}
}
async function getAuthFromOffscreen() {
await setupOffscreenDocument();
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({action: 'getAuth', target: 'offscreen'}, (response) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve(response);
}
});
});
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'signIn') {
getAuthFromOffscreen()
.then(user => {
chrome.storage.local.set({user: user}, () => {
sendResponse({user: user});
});
})
.catch(error => {
console.error('Authentication error:', error);
sendResponse({error: error.message});
});
return true; // Indicates we will send a response asynchronously
} else if (message.action === 'signOut') {
chrome.storage.local.remove('user', () => {
sendResponse();
});
return true;
}
});
f) 在 chrome-extension/offscreen.html
中建立 offscreen.html 文件
<!DOCTYPE html>
<html>
<head>
<title>Offscreen Document</title>
</head>
<body>
<script src="offscreen.js"></script>
</body>
</html>
g) 在 _chrome-extension/offscreen.js 中建立一個 offscreen.js 檔案
_
const FIREBASE_HOSTING_URL = 'https://your-project-id.web.app'; // Replace with your Firebase hosting URL
const iframe = document.createElement('iframe');
iframe.src = FIREBASE_HOSTING_URL;
document.body.appendChild(iframe);
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'getAuth' && message.target === 'offscreen') {
function handleIframeMessage({data}) {
try {
const parsedData = JSON.parse(data);
window.removeEventListener('message', handleIframeMessage);
sendResponse(parsedData.user);
} catch (e) {
console.error('Error parsing iframe message:', e);
}
}
window.addEventListener('message', handleIframeMessage);
iframe.contentWindow.postMessage({initAuth: true}, FIREBASE_HOSTING_URL);
return true; // Indicates we will send a response asynchronously
}
});
步驟 4:設定 Firebase 身份驗證
a) 在 Firebase 控制台中,前往「驗證」>登入方法。
b) 啟用 Google 作為登入提供者。
c) 將您的 Chrome 擴充功能 ID 新增至授權網域清單:
格式為:chrome-extension://YOUR_EXTENSION_ID
作為解壓縮的擴充功能載入後,您可以在 Chrome 的擴充功能管理頁面中找到您的擴充功能 ID。
第 5 步:載入並測試擴展
a) 開啟 Google Chrome 並前往 chrome://extensions/。
b) 啟用右上角的「開發者模式」。
c) 點擊「載入解壓縮」並選擇您的 chrome 擴充目錄。
d) 點擊 Chrome 工具列中的擴充功能圖示以開啟彈出視窗。
e) 點選「登入」按鈕並測試驗證流程。
故障排除
如果您遇到 CORS 問題,請確保在 background.js 和 offscreen.js 中正確設定您的 Firebase 託管 URL。
確保您的 Chrome 擴充功能的 ID 已正確新增至 Firebase 的授權網域。
檢查彈出視窗、背景腳本和螢幕外文件中的控制台日誌是否有任何錯誤訊息。
結論
您現在擁有一個 Chrome 擴充程序,它使用 Firebase 驗證和螢幕外文件來處理登入過程。此設定允許安全身份驗證,而無需直接在擴充程式碼中暴露敏感的 Firebase 配置詳細資訊。
請記得在發布擴充功能之前將佔位符值(例如 YOUR_EXTENSION_ID、YOUR-CLIENT-ID、YOUR_PUBLIC_KEY 和 your-project-id)替換為您的實際值。
以上是使用 Firebase 的 Chrome 擴充功能中的 Google 驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!
熱AI工具
Undress AI Tool
免費脫衣圖片
Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片
AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。
Clothoff.io
AI脫衣器
Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!
熱門文章
熱工具
記事本++7.3.1
好用且免費的程式碼編輯器
SublimeText3漢化版
中文版,非常好用
禪工作室 13.0.1
強大的PHP整合開發環境
Dreamweaver CS6
視覺化網頁開發工具
SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)
如何在JS中與日期和時間合作?
Jul 01, 2025 am 01:27 AM
JavaScript中的日期和時間處理需注意以下幾點:1.創建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區問題建議使用支持時區的庫,如Luxon。掌握這些要點能有效避免常見錯誤。
為什麼要將標籤放在的底部?
Jul 02, 2025 am 01:22 AM
PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl
什麼是在DOM中冒泡和捕獲的事件?
Jul 02, 2025 am 01:19 AM
事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數設為true實現;2.事件冒泡是默認行為,useCapture設為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態內容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應用戶操作的時機和方式。
如何減少JavaScript應用程序的有效載荷大小?
Jun 26, 2025 am 12:54 AM
如果JavaScript應用加載慢、性能差,問題往往出在payload太大,解決方法包括:1.使用代碼拆分(CodeSplitting),通過React.lazy()或構建工具將大bundle拆分為多個小文件,按需加載以減少首次下載量;2.移除未使用的代碼(TreeShaking),利用ES6模塊機制清除“死代碼”,確保引入的庫支持該特性;3.壓縮和合併資源文件,啟用Gzip/Brotli和Terser壓縮JS,合理合併文件並優化靜態資源;4.替換重型依賴,選用輕量級庫如day.js、fetch
JavaScript模塊上的確定JS綜述:ES模塊與COMPORJS
Jul 02, 2025 am 01:28 AM
ES模塊和CommonJS的主要區別在於加載方式和使用場景。 1.CommonJS是同步加載,適用於Node.js服務器端環境;2.ES模塊是異步加載,適用於瀏覽器等網絡環境;3.語法上,ES模塊使用import/export,且必須位於頂層作用域,而CommonJS使用require/module.exports,可在運行時動態調用;4.CommonJS廣泛用於舊版Node.js及依賴它的庫如Express,ES模塊則適用於現代前端框架和Node.jsv14 ;5.雖然可混合使用,但容易引發問題
如何在node.js中提出HTTP請求?
Jul 13, 2025 am 02:18 AM
在Node.js中發起HTTP請求有三種常用方式:使用內置模塊、axios和node-fetch。 1.使用內置的http/https模塊無需依賴,適合基礎場景,但需手動處理數據拼接和錯誤監聽,例如用https.get()獲取數據或通過.write()發送POST請求;2.axios是基於Promise的第三方庫,語法簡潔且功能強大,支持async/await、自動JSON轉換、攔截器等,推薦用於簡化異步請求操作;3.node-fetch提供類似瀏覽器fetch的風格,基於Promise且語法簡單
編寫清潔和可維護的JavaScript代碼的最佳實踐是什麼?
Jun 23, 2025 am 12:35 AM
要寫出乾淨、可維護的JavaScript代碼,應遵循以下四點:1.使用清晰一致的命名規範,變量名用名詞如count,函數名用動詞開頭如fetchData(),類名用PascalCase如UserProfile;2.避免過長函數和副作用,每個函數只做一件事,如將更新用戶信息拆分為formatUser、saveUser和renderUser;3.合理使用模塊化和組件化,如在React中將頁面拆分為UserProfile、UserStats等小組件;4.寫註釋和文檔時點到為止,重點說明關鍵邏輯、算法選
var vs Let vs const:快速JS綜述解釋器
Jul 02, 2025 am 01:18 AM
var、let和const的區別在於作用域、提升和重複聲明。 1.var是函數作用域,存在變量提升,允許重複聲明;2.let是塊級作用域,存在暫時性死區,不允許重複聲明;3.const也是塊級作用域,必須立即賦值,不可重新賦值,但可修改引用類型的內部值。優先使用const,需改變變量時用let,避免使用var。


