gsdf
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import db from '../../sql.mjs';
|
||||
import lib from '../../lib.mjs';
|
||||
import cfg from '../../config.mjs';
|
||||
import { parseOpenSshPubkey, verifySignature, getOrCreateAnonUser, createAnonSession } from '../../anon_auth.mjs';
|
||||
import { getEnableAnonymousAccess } from '../../settings.mjs';
|
||||
|
||||
export default router => {
|
||||
router.group(/^\/api\/v2\/anon/, group => {
|
||||
|
||||
/**
|
||||
* POST /api/v2/anon/session
|
||||
* Authenticate via OpenSSH Ed25519 signature and establish an anonymous session.
|
||||
*/
|
||||
group.post(/\/session$/, async (req, res) => {
|
||||
try {
|
||||
if (!getEnableAnonymousAccess()) {
|
||||
return res.json({ success: false, msg: 'Anonymous access is disabled' }, 403);
|
||||
}
|
||||
|
||||
const body = req.post || req.body || {};
|
||||
const pubkey = (body.pubkey || '').trim();
|
||||
const timestamp = parseInt(body.timestamp, 10);
|
||||
const signature = (body.signature || '').trim();
|
||||
|
||||
if (!pubkey || !timestamp || !signature) {
|
||||
return res.json({ success: false, msg: 'Missing pubkey, timestamp, or signature' }, 400);
|
||||
}
|
||||
|
||||
// Freshness check (5-minute window for clock skew)
|
||||
const now = Date.now();
|
||||
if (Math.abs(now - timestamp) > 300000) {
|
||||
return res.json({ success: false, msg: 'Timestamp expired or out of bounds' }, 401);
|
||||
}
|
||||
|
||||
const message = `anon-auth:${timestamp}:${pubkey}`;
|
||||
const isValid = verifySignature(pubkey, message, signature);
|
||||
if (!isValid) {
|
||||
return res.json({ success: false, msg: 'Invalid Ed25519 signature' }, 401);
|
||||
}
|
||||
|
||||
const parsed = parseOpenSshPubkey(pubkey);
|
||||
const { userId, isNew } = await getOrCreateAnonUser(pubkey, parsed.fingerprint);
|
||||
const { session, csrf_token } = await createAnonSession(userId, req);
|
||||
|
||||
res.setHeader('Set-Cookie', `session=${session}; ${lib.getCookieOptions('Fri, 31 Dec 9999 23:59:59 GMT')}`);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
is_new: isNew,
|
||||
user_id: userId,
|
||||
fingerprint: parsed.fingerprint,
|
||||
short_fingerprint: parsed.shortFingerprint,
|
||||
csrf_token: csrf_token
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ANON_AUTH] Session establishment error:', err);
|
||||
return res.json({ success: false, msg: err.message || 'Internal server error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/v2/anon/identity
|
||||
* Get the current anonymous identity or registered user state.
|
||||
*/
|
||||
group.get(/\/identity$/, async (req, res) => {
|
||||
try {
|
||||
if (!getEnableAnonymousAccess()) {
|
||||
return res.json({ logged_in: false, is_anon: false, disabled: true });
|
||||
}
|
||||
|
||||
if (!req.session) {
|
||||
return res.json({ logged_in: false, is_anon: false });
|
||||
}
|
||||
|
||||
const rows = await db`
|
||||
SELECT pubkey, fingerprint, created_at, last_seen
|
||||
FROM anon_identities
|
||||
WHERE user_id = ${req.session.id}
|
||||
LIMIT 1
|
||||
`;
|
||||
|
||||
if (rows.length > 0) {
|
||||
const fp = rows[0].fingerprint;
|
||||
return res.json({
|
||||
logged_in: true,
|
||||
is_anon: true,
|
||||
user_id: req.session.id,
|
||||
fingerprint: fp,
|
||||
short_fingerprint: fp.slice(7, 15),
|
||||
pubkey: rows[0].pubkey,
|
||||
csrf_token: req.session.csrf_token
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({
|
||||
logged_in: true,
|
||||
is_anon: false,
|
||||
user: req.session.user,
|
||||
user_id: req.session.id,
|
||||
csrf_token: req.session.csrf_token
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[ANON_AUTH] Identity lookup error:', err);
|
||||
return res.json({ success: false, msg: err.message }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/v2/anon/logout
|
||||
* Clear anonymous session cookie and remove active session from database.
|
||||
*/
|
||||
group.post(/\/logout$/, async (req, res) => {
|
||||
try {
|
||||
if (req.session && req.session.sess_id) {
|
||||
await db`
|
||||
DELETE FROM user_sessions
|
||||
WHERE id = ${+req.session.sess_id}
|
||||
`;
|
||||
}
|
||||
res.setHeader('Set-Cookie', `session=; ${lib.getCookieOptions('Thu, 01 Jan 1970 00:00:00 GMT')}`);
|
||||
return res.json({ success: true });
|
||||
} catch (err) {
|
||||
console.error('[ANON_AUTH] Logout error:', err);
|
||||
return res.json({ success: false, msg: err.message }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user