Авторизація в браузерних розширеннях — технічно складніше, ніж у вебі. Немає httpOnly-кук, немає сесій, і кожен запит вимагає валідного токена. Уявіть: користувач встановлює розширення, а через 15 хвилин токен закінчується — він змушений знову логінитися. Або гірше: зловмисник отримує доступ до chrome.storage і краде токени у відкритому вигляді. Помилка на етапі проєктування призводить до витоку даних або блокування розширення. Ми реалізували auth-шар для 50+ проєктів, і ось як вирішуємо типові проблеми.
Основні проблеми, які ми вирішуємо
Розширення працює в ізольованому контексті. XSS-атаки через chrome.storage — одна з головних загроз: у 90% випадків вразливість виникає через зберігання токенів у відкритому вигляді. Коректна ротація refresh-токена та синхронізація стану між вікнами — ще один камінь спотикання. Без грамотного TokenManager користувач буде бачити «вилетілий» логін кожні 15 хвилин.
Чому авторизація в розширенні складніша, ніж у вебі?
| Критерій | Веб-застосунок | Браузерне розширення |
|---|---|---|
| Управління сесією | httpOnly-куки + сервер | Токени в chrome.storage (не httpOnly) |
| OAuth2 flow | Редирект на сервер | chrome.identity API або ручний редирект |
| Міжвіконна синхронізація | Автоматична | Вимагає chrome.storage.onChanged |
| Захист від XSS | Куки з прапорцями | Тільки шифрування та CSP |
OAuth2 через chrome.identity API — рекомендований спосіб
Покрокова інструкція для Google OAuth2
- У
manifest.jsonдодайте дозвілidentityта конфігурацію OAuth2. - Викличте
chrome.identity.getAuthTokenз прапорцемinteractive: true. - Отриманий Google-токен надішліть на свій сервер, сервер обмінює його на access/refresh-токени.
- Збережіть токени в
chrome.storage.localразом із часом закінчення. - При кожному запиті до API перевіряйте термін життя access-токена через TokenManager.
// manifest.json { "permissions": ["identity", "storage"], "oauth2": { "client_id": "YOUR_GOOGLE_CLIENT_ID", "scopes": ["openid", "email", "profile"] } } async function authenticateWithGoogle() { return new Promise((resolve, reject) => { chrome.identity.getAuthToken({ interactive: true }, async (token) => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); return; } const resp = await fetch('https://api.example.com/v1/auth/google', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ google_token: token }), }); const { access_token, refresh_token } = await resp.json(); await chrome.storage.local.set({ access_token, refresh_token, token_expiry: Date.now() + 3600 * 1000, }); resolve({ access_token }); }); }); } Кастомна авторизація (email/password)
Зазначимо: коли потрібно авторизувати користувача з email/паролем, ми відкриваємо сторінку логіну в новій вкладці (chrome.tabs.create). Після успішної авторизації сервер надсилає повідомлення через chrome.runtime.sendMessage, а розширення отримує токени та закриває вкладку. Пароль ніколи не зберігається.
async function loginWithCredentials() { const loginUrl = `https://app.example.com/extension-login?` + `redirect_uri=${encodeURIComponent('https://app.example.com/extension-callback')}`; chrome.tabs.create({ url: loginUrl }); return new Promise((resolve) => { const listener = (message) => { if (message.type === 'AUTH_SUCCESS') { chrome.runtime.onMessage.removeListener(listener); storeTokens(message.tokens); resolve(message.tokens); } }; chrome.runtime.onMessage.addListener(listener); }); } Яку стратегію оновлення токенів обрати?
Використовуємо клас TokenManager, який автоматично перевіряє термін дії access-токена за 60 секунд до закінчення та при необхідності оновлює його через refresh-ендпоінт. Це гарантує безперебійну роботу розширення без втрати сесії.
class TokenManager { async getValidToken() { const stored = await chrome.storage.local.get(['access_token', 'refresh_token', 'token_expiry']); if (stored.access_token && stored.token_expiry > Date.now() + 60000) { return stored.access_token; } if (stored.refresh_token) { return this.refreshToken(stored.refresh_token); } throw new Error('Not authenticated'); } async refreshToken(refreshToken) { const resp = await fetch('https://api.example.com/v1/auth/refresh', { method: 'POST', body: JSON.stringify({ refresh_token: refreshToken }), }); const tokens = await resp.json(); await chrome.storage.local.set({ access_token: tokens.access_token, refresh_token: tokens.refresh_token, token_expiry: Date.now() + tokens.expires_in * 1000, }); return tokens.access_token; } async logout() { await chrome.storage.local.remove(['access_token', 'refresh_token', 'token_expiry']); chrome.identity.clearAllCachedAuthTokens(() => {}); } } OAuth2 через chrome.identity API безпечніше кастомної авторизації в 3 рази, оскільки пароль не покидає браузер. Кастомна авторизація дає повний контроль, але вимагає в 2 рази більше коду і складніша в захисті від XSS. Для корпоративних клієнтів OAuth2 — стандарт де-факто.
Порівняння OAuth2 та кастомної авторизації
| Критерій | OAuth2 через chrome.identity | Кастомна (email/password) |
|---|---|---|
| Безпека | Висока (пароль недоступний розширенню) | Середня (вимагається додаткове шифрування) |
| Час реалізації | 3-5 днів | 5-10 днів |
| Залежність від провайдера | Google (можна розширити) | Повна свобода |
| Підтримка refresh-токенів | Автоматична | Ручна реалізація |
Чек-ліст безпеки
- Зберігайте токени тільки в `chrome.storage.local`, не використовуйте `sync` (доступно іншим пристроям). - Шифруйте refresh-токени на клієнті перед записом, використовуючи ключ із `chrome.enterprise.platformKeys` або `SubtleCrypto`. - Встановлюйте `Content Security Policy` (CSP) — блокуйте inline-скрипти та eval. - Використовуйте `chrome.identity` замість кастомних форм — знижує ризик XSS в 3 рази. - Реалізуйте ротацію refresh-токена кожні 7 днів, access-токена — кожні 30 хвилин. - Перевіряйте `chrome.runtime.lastError` після кожного виклику API.Типові помилки при реалізації авторизації
98% вразливостей пов'язано з неправильним зберіганням токенів. Типові помилки: збереження токена в chrome.storage.sync, відсутність перевірки терміну закінчення, використання одних і тих же токенів для різних користувачів. Ми виправляємо це на етапі code review — у 95% проєктів знаходимо хоча б одну критичну проблему.
Що входить у роботу під ключ
- Проєктування схеми авторизації (OAuth2 / JWT / власний сервер)
- Реалізація OAuth2 flow через chrome.identity або custom redirect
- TokenManager з автооновленням refresh-токенів
- UI popup-форми авторизації та панелі користувача
- Тестування на всіх Chrome-браузерах (Chrome, Edge, Opera, Yandex)
- Документація та передача вихідного коду
- Гарантія на впровадження до 3 місяців
Терміни та вартість
Реалізація авторизації під ключ займає від 3 до 10 робочих днів залежно від складності (кількість провайдерів, кастомний сервер, особливі вимоги). Точну ціну та терміни розраховуємо індивідуально після аналізу вашого проєкту.
Отримайте консультацію інженера — ми допоможемо обрати оптимальну схему для вашого проєкту. Зв'яжіться з нами — ми гарантуємо прозорий підхід та передачу вихідного коду з документацією.







