token usage tightened with revocation
This commit is contained in:
+63
-13
@@ -13,6 +13,7 @@ const feedLink = document.getElementById('feed-link');
|
||||
const authWarning = document.getElementById('auth-warning');
|
||||
const warningSettingsButton = document.getElementById('warning-settings');
|
||||
const authSession = document.getElementById('auth-session');
|
||||
const sessionStore = browser.storage.session;
|
||||
|
||||
const t = window.linklogI18n;
|
||||
|
||||
@@ -42,12 +43,49 @@ function setStatus(message, isError = false) {
|
||||
}
|
||||
|
||||
async function getSettings() {
|
||||
const result = await browser.storage.local.get([
|
||||
'backendUrl',
|
||||
'accessToken',
|
||||
'tokenExpiresAt',
|
||||
const [settings, sessionSettings] = await Promise.all([
|
||||
browser.storage.local.get(['backendUrl', 'username']),
|
||||
sessionStore.get(['accessToken', 'refreshToken', 'tokenExpiresAt', 'deviceId']),
|
||||
]);
|
||||
return result;
|
||||
return {...settings, ...sessionSettings};
|
||||
}
|
||||
|
||||
async function persistSession(settings) {
|
||||
await sessionStore.set({
|
||||
accessToken: settings.accessToken,
|
||||
refreshToken: settings.refreshToken,
|
||||
tokenExpiresAt: settings.tokenExpiresAt,
|
||||
deviceId: settings.deviceId,
|
||||
});
|
||||
}
|
||||
|
||||
async function clearSession() {
|
||||
await Promise.all([
|
||||
sessionStore.remove(['accessToken', 'refreshToken', 'tokenExpiresAt', 'deviceId']),
|
||||
browser.storage.local.remove(['accessToken', 'tokenType', 'tokenExpiresAt', 'refreshToken', 'deviceId']),
|
||||
]);
|
||||
}
|
||||
|
||||
async function refreshAccessToken(settings) {
|
||||
if (!settings.backendUrl || !settings.refreshToken || !settings.deviceId) return null;
|
||||
try {
|
||||
const response = await fetch(`${settings.backendUrl}/api/auth/refresh`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({refresh_token: settings.refreshToken, device_id: settings.deviceId}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
await clearSession();
|
||||
return null;
|
||||
}
|
||||
const data = await response.json();
|
||||
const refreshed = {...settings, accessToken: data.access_token, refreshToken: data.refresh_token,
|
||||
tokenExpiresAt: data.expires_at, deviceId: data.device_id || settings.deviceId};
|
||||
await persistSession(refreshed);
|
||||
return refreshed;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function validateSession(settings) {
|
||||
@@ -57,7 +95,16 @@ async function validateSession(settings) {
|
||||
headers: {'Authorization': `Bearer ${settings.accessToken}`},
|
||||
});
|
||||
if (!response.ok) {
|
||||
await browser.storage.local.remove(['accessToken', 'tokenType', 'tokenExpiresAt', 'refreshToken']);
|
||||
if (response.status === 401) {
|
||||
const refreshed = await refreshAccessToken(settings);
|
||||
if (refreshed) {
|
||||
const retry = await fetch(`${refreshed.backendUrl}/api/auth/me`, {
|
||||
headers: {'Authorization': `Bearer ${refreshed.accessToken}`},
|
||||
});
|
||||
if (retry.ok) return await retry.json();
|
||||
}
|
||||
}
|
||||
await clearSession();
|
||||
return null;
|
||||
}
|
||||
return await response.json();
|
||||
@@ -97,7 +144,7 @@ function showSavedState(message) {
|
||||
}
|
||||
|
||||
async function updateFeedLink() {
|
||||
const settings = await browser.storage.local.get(['backendUrl', 'username', 'accessToken']);
|
||||
const settings = await getSettings();
|
||||
if (!settings.backendUrl || !settings.username || !settings.accessToken) return;
|
||||
try {
|
||||
const backend = new URL(settings.backendUrl);
|
||||
@@ -119,9 +166,10 @@ async function loadExistingTags() {
|
||||
showSignedOutState();
|
||||
return;
|
||||
}
|
||||
showSignedInState(user, settings.backendUrl);
|
||||
const response = await fetch(`${settings.backendUrl}/api/tags`, {
|
||||
headers: {'Authorization': `Bearer ${settings.accessToken}`},
|
||||
const currentSettings = await getSettings();
|
||||
showSignedInState(user, currentSettings.backendUrl);
|
||||
const response = await fetch(`${currentSettings.backendUrl}/api/tags`, {
|
||||
headers: {'Authorization': `Bearer ${currentSettings.accessToken}`},
|
||||
});
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
@@ -212,12 +260,14 @@ async function handleSubmit(event) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSettings = await getSettings();
|
||||
|
||||
try {
|
||||
const response = await fetch(`${backendUrl}/api/links`, {
|
||||
const response = await fetch(`${currentSettings.backendUrl}/api/links`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Authorization': `Bearer ${currentSettings.accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: titleInput.value,
|
||||
@@ -240,7 +290,7 @@ async function handleSubmit(event) {
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
const saveMessage = result.duplicate ? t('linkAlreadyExists') : t('linkSaved', backendUrl);
|
||||
const saveMessage = result.duplicate ? t('linkAlreadyExists') : t('linkSaved', currentSettings.backendUrl);
|
||||
if (result.plugin_errors?.length) {
|
||||
const errors = result.plugin_errors.map((error) => `${error.plugin}: ${error.reason}`).join(' ');
|
||||
showSavedState(`${saveMessage} ${t('publishingErrors', errors)}`);
|
||||
|
||||
Reference in New Issue
Block a user