Skip to content

Commit d40de28

Browse files
committed
feat(browser): add zhiz.chat sso flow and auth callback
1 parent 3fbda6b commit d40de28

12 files changed

Lines changed: 1314 additions & 122 deletions

File tree

browser/background/service-worker.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { Defaults } from "../shared/defaults.js";
2020
import { Api } from "../shared/api.js";
2121
import { Scenes } from "../shared/scenes.js";
2222
import { Router } from "../shared/router.js";
23+
// 2026-04-10 SSO B2: Token 自动刷新
24+
import { Sso } from "../shared/sso.js";
2325

2426
let _backgroundInitialized = false;
2527

@@ -124,6 +126,78 @@ export function setupBackground() {
124126
}
125127
});
126128

129+
/* ─── SSO Token Refresh Alarm (B2) ─── */
130+
// 2026-04-10 新增 — SSO Plan v2 B2
131+
// 设计思路:
132+
// 1. 扩展安装/启动时检查 token 过期时间,设置 chrome.alarms 定时刷新
133+
// 2. Alarm 在 token 过期前 5 分钟触发(最小间隔 50 分钟)
134+
// 3. 刷新失败不阻塞正常功能(匿名模式仍可用)
135+
// 影响范围:background service-worker,不影响 popup/content
136+
// 潜在风险:service worker 被浏览器休眠后 alarm 可能延迟,但 401 重试兜底
137+
138+
const SSO_REFRESH_ALARM = "ep-sso-token-refresh";
139+
const REFRESH_BUFFER_MS = 5 * 60 * 1000; // 提前 5 分钟刷新
140+
const MIN_ALARM_INTERVAL_MIN = 50; // 最小定时间隔(分钟)
141+
142+
/**
143+
* 根据 token 过期时间调度下次刷新 alarm
144+
* 无 token 时清除 alarm
145+
*/
146+
async function scheduleTokenRefresh() {
147+
const expiresAt = await Sso.getExpiresAt();
148+
if (!expiresAt) {
149+
// 无 token,清除 alarm
150+
chrome.alarms.clear(SSO_REFRESH_ALARM);
151+
return;
152+
}
153+
154+
const now = Date.now();
155+
const refreshAt = expiresAt - REFRESH_BUFFER_MS;
156+
const delayMs = Math.max(refreshAt - now, 60 * 1000); // 至少 1 分钟后
157+
const delayMin = delayMs / 60000;
158+
159+
// 设置一次性 alarm + 周期性兜底(防止单次 alarm 丢失)
160+
chrome.alarms.create(SSO_REFRESH_ALARM, {
161+
delayInMinutes: delayMin,
162+
periodInMinutes: MIN_ALARM_INTERVAL_MIN,
163+
});
164+
}
165+
166+
// 安装/启动时调度
167+
chrome.runtime.onInstalled.addListener(() => scheduleTokenRefresh());
168+
chrome.runtime.onStartup.addListener(() => scheduleTokenRefresh());
169+
170+
// Alarm 触发时刷新 token
171+
chrome.alarms.onAlarm.addListener(async (alarm) => {
172+
if (alarm.name !== SSO_REFRESH_ALARM) return;
173+
174+
const token = await Sso.getAccessToken();
175+
if (!token) {
176+
// 用户已退出,清除 alarm
177+
chrome.alarms.clear(SSO_REFRESH_ALARM);
178+
return;
179+
}
180+
181+
try {
182+
await Sso.refreshAccessToken();
183+
// 刷新成功,重新调度下次刷新
184+
await scheduleTokenRefresh();
185+
console.log("[EP] SSO token refreshed successfully");
186+
} catch (err) {
187+
// 刷新失败(refresh token 过期等),清除 alarm
188+
// 用户下次请求会收到 401,需重新登录
189+
console.warn("[EP] SSO token refresh failed:", err.message);
190+
chrome.alarms.clear(SSO_REFRESH_ALARM);
191+
}
192+
});
193+
194+
// 监听 storage 变化:登录/退出时重新调度
195+
chrome.storage.onChanged.addListener((changes) => {
196+
if (changes[Sso.SSO_KEYS.EXPIRES_AT]) {
197+
scheduleTokenRefresh();
198+
}
199+
});
200+
127201
/* ─── Inline Enhance (AI 聊天网站原地增强) ─── */
128202

129203
/**

0 commit comments

Comments
 (0)