@syncello/auth 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1190,6 +1190,19 @@ var problems = {
1190
1190
  };
1191
1191
 
1192
1192
  // src/middleware/auth.ts
1193
+ var SESSION_MAX_LIFETIME_MS = AUTH_DEFAULTS.SESSION_MAX_LIFETIME_DAYS * 24 * 60 * 60 * 1e3;
1194
+ async function revokeIfPastMaxLifetime(db, sessions, sessionId, session) {
1195
+ if (Date.now() - session.createdAt <= SESSION_MAX_LIFETIME_MS) return false;
1196
+ logger_default.info("Session exceeded absolute lifetime - revoked", {
1197
+ type: "security",
1198
+ event: "session_max_lifetime_exceeded",
1199
+ severity: "low",
1200
+ sessionId: sessionId.slice(0, 8),
1201
+ userId: session.userId
1202
+ });
1203
+ await deleteSession(db, { sessions }, sessionId);
1204
+ return true;
1205
+ }
1193
1206
  async function getSessionFromCookie(db, sessions, cookieHeader, request, env) {
1194
1207
  const cookieName = getSessionCookieName(env);
1195
1208
  const cookiePattern = new RegExp(`${cookieName}=([^;]+)`);
@@ -1199,10 +1212,13 @@ async function getSessionFromCookie(db, sessions, cookieHeader, request, env) {
1199
1212
  const foundSessions = await db.select({
1200
1213
  userId: sessions.userId,
1201
1214
  expiresAt: sessions.expiresAt,
1215
+ createdAt: sessions.createdAt,
1202
1216
  fingerprint: sessions.fingerprint
1203
1217
  }).from(sessions).where(and2(eq4(sessions.id, sessionId), gt2(sessions.expiresAt, Date.now()))).limit(1);
1204
1218
  if (foundSessions.length === 0) return null;
1205
1219
  const session = foundSessions[0];
1220
+ if (await revokeIfPastMaxLifetime(db, sessions, sessionId, session)) return null;
1221
+ await refreshSession(db, { sessions }, sessionId);
1206
1222
  const userAgent = request.headers.get("user-agent") || "";
1207
1223
  const cfWorker = request.headers.get("cf-worker") || "";
1208
1224
  const clientIp = request.headers.get("cf-connecting-ip") || request.headers.get("x-real-ip") || "";
@@ -1246,10 +1262,12 @@ async function getSessionFromBearerToken(db, sessions, authHeader) {
1246
1262
  const sessionId = authHeader.slice(7);
1247
1263
  const foundSessions = await db.select({
1248
1264
  userId: sessions.userId,
1249
- expiresAt: sessions.expiresAt
1265
+ expiresAt: sessions.expiresAt,
1266
+ createdAt: sessions.createdAt
1250
1267
  }).from(sessions).where(and2(eq4(sessions.id, sessionId), gt2(sessions.expiresAt, Date.now()))).limit(1);
1251
1268
  if (foundSessions.length === 0) return null;
1252
1269
  const session = foundSessions[0];
1270
+ if (await revokeIfPastMaxLifetime(db, sessions, sessionId, session)) return null;
1253
1271
  await refreshSession(db, { sessions }, sessionId);
1254
1272
  return {
1255
1273
  userId: session.userId,
@@ -4412,10 +4430,10 @@ var statusRoute = createRoute16({
4412
4430
  content: { "application/json": { schema: statusResponseSchema } },
4413
4431
  headers: {
4414
4432
  "Cache-Control": {
4415
- description: "Cache for 24 hours",
4433
+ description: "Cache for 60 seconds",
4416
4434
  schema: {
4417
4435
  type: "string",
4418
- example: "private, max-age=86400, stale-while-revalidate=3600"
4436
+ example: "private, max-age=60"
4419
4437
  }
4420
4438
  }
4421
4439
  }
@@ -4432,7 +4450,7 @@ var statusHandler = async (c) => {
4432
4450
  const { db, schema } = getAuthContext(c);
4433
4451
  const methods = await getUserEnabled2faMethods(db, userId, schema.user2faMethods);
4434
4452
  const backupCodes = await db.select({ id: schema.userBackupCodes.id }).from(schema.userBackupCodes).where(and7(eq19(schema.userBackupCodes.userId, userId), isNull2(schema.userBackupCodes.usedAt)));
4435
- c.header("Cache-Control", "private, max-age=86400, stale-while-revalidate=3600");
4453
+ c.header("Cache-Control", "private, max-age=60");
4436
4454
  c.header("Vary", "Cookie");
4437
4455
  return c.json({
4438
4456
  enabled: methods.length > 0,
@@ -4923,10 +4941,10 @@ var trustedDevicesGetRoute = createRoute24({
4923
4941
  content: { "application/json": { schema: trustedDevicesResponseSchema } },
4924
4942
  headers: {
4925
4943
  "Cache-Control": {
4926
- description: "Cache for 24 hours",
4944
+ description: "Cache for 60 seconds",
4927
4945
  schema: {
4928
4946
  type: "string",
4929
- example: "private, max-age=86400, stale-while-revalidate=3600"
4947
+ example: "private, max-age=60"
4930
4948
  }
4931
4949
  }
4932
4950
  }
@@ -4950,7 +4968,7 @@ var trustedDevicesGetHandler = async (c) => {
4950
4968
  lastUsedAt: schema.userTrustedDevices.lastUsedAt,
4951
4969
  createdAt: schema.userTrustedDevices.createdAt
4952
4970
  }).from(schema.userTrustedDevices).where(and13(eq27(schema.userTrustedDevices.userId, userId), gt5(schema.userTrustedDevices.expiresAt, now)));
4953
- c.header("Cache-Control", "private, max-age=86400, stale-while-revalidate=3600");
4971
+ c.header("Cache-Control", "private, max-age=60");
4954
4972
  c.header("Vary", "Cookie");
4955
4973
  return c.json({ devices });
4956
4974
  };