Авторизація в браузерних розширеннях — технічно складніше, ніж у вебі. Немає 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 робочих днів залежно від складності (кількість провайдерів, кастомний сервер, особливі вимоги). Точну ціну та терміни розраховуємо індивідуально після аналізу вашого проєкту.
Отримайте консультацію інженера — ми допоможемо обрати оптимальну схему для вашого проєкту. Зв'яжіться з нами — ми гарантуємо прозорий підхід та передачу вихідного коду з документацією.







