refactor(auth): migrate session storage to JWT with persistent secret (#508)

- Replace in-memory session Map with stateless JWT tokens
- Add jose library for JWT signing and verification
- Implement persistent JWT secret storage in ~/.config/openchamber
- Support OPENCODE_JWT_SECRET environment variable override
- Update SessionAuthGate and useServerSessionStatus hooks
- Remove session cleanup timer (JWTs are stateless)

Co-authored-by: Jovines <jovines@qq.com>
This commit is contained in:
Jovines
2026-02-25 19:40:28 +02:00
committed by GitHub
co-authored by Jovines
parent 5473381720
commit 7a151290be
6 changed files with 130 additions and 69 deletions
+18 -6
View File
@@ -5713,10 +5713,22 @@ async function main(options = {}) {
console.log('UI password protection enabled for browser sessions');
}
app.get('/auth/session', (req, res) => uiAuthController.handleSessionStatus(req, res));
app.get('/auth/session', async (req, res) => {
try {
await uiAuthController.handleSessionStatus(req, res);
} catch (err) {
res.status(500).json({ error: 'Internal server error' });
}
});
app.post('/auth/session', (req, res) => uiAuthController.handleSessionCreate(req, res));
app.use('/api', (req, res, next) => uiAuthController.requireAuth(req, res, next));
app.use('/api', async (req, res, next) => {
try {
await uiAuthController.requireAuth(req, res, next);
} catch (err) {
next(err);
}
});
const parsePushSubscribeBody = (body) => {
if (!body || typeof body !== 'object') return null;
@@ -5757,7 +5769,7 @@ async function main(options = {}) {
await ensurePushInitialized();
const uiToken = uiAuthController?.ensureSessionToken
? uiAuthController.ensureSessionToken(req, res)
? await uiAuthController.ensureSessionToken(req, res)
: getUiSessionTokenFromRequest(req);
if (!uiToken) {
return res.status(401).json({ error: 'UI session missing' });
@@ -5805,7 +5817,7 @@ async function main(options = {}) {
await ensurePushInitialized();
const uiToken = uiAuthController?.ensureSessionToken
? uiAuthController.ensureSessionToken(req, res)
? await uiAuthController.ensureSessionToken(req, res)
: getUiSessionTokenFromRequest(req);
if (!uiToken) {
return res.status(401).json({ error: 'UI session missing' });
@@ -5820,9 +5832,9 @@ async function main(options = {}) {
res.json({ ok: true });
});
app.post('/api/push/visibility', (req, res) => {
app.post('/api/push/visibility', async (req, res) => {
const uiToken = uiAuthController?.ensureSessionToken
? uiAuthController.ensureSessionToken(req, res)
? await uiAuthController.ensureSessionToken(req, res)
: getUiSessionTokenFromRequest(req);
if (!uiToken) {
return res.status(401).json({ error: 'UI session missing' });