effortless-aws 0.27.1 → 0.29.0

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.
@@ -251,7 +251,8 @@ var toSeconds = (d) => {
251
251
 
252
252
  // src/handlers/auth.ts
253
253
  var AUTH_COOKIE_NAME = "__eff_session";
254
- var createAuthRuntime = (secret, defaultExpiresIn) => {
254
+ var createAuthRuntime = (secret, defaultExpiresIn, apiTokenVerify, apiTokenHeader, apiTokenCacheTtlSeconds) => {
255
+ const tokenCache = apiTokenCacheTtlSeconds ? /* @__PURE__ */ new Map() : void 0;
255
256
  const sign = (payload) => crypto.createHmac("sha256", secret).update(payload).digest("base64url");
256
257
  const cookieBase = `${AUTH_COOKIE_NAME}=`;
257
258
  const cookieAttrs = "; HttpOnly; Secure; SameSite=Lax; Path=/";
@@ -271,36 +272,55 @@ var createAuthRuntime = (secret, defaultExpiresIn) => {
271
272
  return void 0;
272
273
  }
273
274
  };
274
- return {
275
- forRequest(cookieValue) {
275
+ const extractTokenValue = (headerValue) => {
276
+ const isDefaultHeader = !apiTokenHeader || apiTokenHeader.toLowerCase() === "authorization";
277
+ if (isDefaultHeader && headerValue.toLowerCase().startsWith("bearer ")) {
278
+ return headerValue.slice(7);
279
+ }
280
+ return headerValue;
281
+ };
282
+ const buildHelpers = (sessionData) => ({
283
+ createSession(data, options) {
284
+ const seconds = options?.expiresIn ? toSeconds(options.expiresIn) : defaultExpiresIn;
285
+ const exp = Math.floor(Date.now() / 1e3) + seconds;
286
+ const payload = Buffer.from(JSON.stringify({ exp, ...data }), "utf-8").toString("base64url");
287
+ const sig = sign(payload);
276
288
  return {
277
- grant(...args) {
278
- const hasData = args.length > 0 && (typeof args[0] === "object" && args[0] !== null && !("expiresIn" in args[0]));
279
- const data = hasData ? args[0] : void 0;
280
- const options = hasData ? args[1] : args[0];
281
- const seconds = options?.expiresIn ? toSeconds(options.expiresIn) : defaultExpiresIn;
282
- const exp = Math.floor(Date.now() / 1e3) + seconds;
283
- const payload = Buffer.from(JSON.stringify({ exp, ...data }), "utf-8").toString("base64url");
284
- const sig = sign(payload);
285
- return {
286
- status: 200,
287
- body: { ok: true },
288
- headers: {
289
- "set-cookie": `${cookieBase}${payload}.${sig}${cookieAttrs}; Max-Age=${seconds}`
290
- }
291
- };
292
- },
293
- revoke() {
294
- return {
295
- status: 200,
296
- body: { ok: true },
297
- headers: {
298
- "set-cookie": `${cookieBase}${cookieAttrs}; Max-Age=0`
299
- }
300
- };
301
- },
302
- session: decodeSession(cookieValue)
289
+ status: 200,
290
+ body: { ok: true },
291
+ headers: {
292
+ "set-cookie": `${cookieBase}${payload}.${sig}${cookieAttrs}; Max-Age=${seconds}`
293
+ }
294
+ };
295
+ },
296
+ clearSession() {
297
+ return {
298
+ status: 200,
299
+ body: { ok: true },
300
+ headers: {
301
+ "set-cookie": `${cookieBase}${cookieAttrs}; Max-Age=0`
302
+ }
303
303
  };
304
+ },
305
+ session: sessionData
306
+ });
307
+ return {
308
+ async forRequest(cookieValue, authHeader) {
309
+ if (authHeader && apiTokenVerify) {
310
+ const tokenValue = extractTokenValue(authHeader);
311
+ if (tokenCache) {
312
+ const cached = tokenCache.get(tokenValue);
313
+ if (cached && cached.expiresAt > Date.now()) {
314
+ return buildHelpers(cached.session);
315
+ }
316
+ }
317
+ const session = await apiTokenVerify({ value: tokenValue });
318
+ if (tokenCache && apiTokenCacheTtlSeconds) {
319
+ tokenCache.set(tokenValue, { session, expiresAt: Date.now() + apiTokenCacheTtlSeconds * 1e3 });
320
+ }
321
+ return buildHelpers(session);
322
+ }
323
+ return buildHelpers(decodeSession(cookieValue));
304
324
  }
305
325
  };
306
326
  };
@@ -478,7 +498,6 @@ var getParameters = async (names) => {
478
498
  // src/runtime/handler-utils.ts
479
499
  var ENV_DEP_PREFIX = "EFF_DEP_";
480
500
  var ENV_PARAM_PREFIX = "EFF_PARAM_";
481
- var ENV_AUTH_SECRET = "EFF_AUTH_SECRET";
482
501
  var LOG_RANK = { error: 0, info: 1, debug: 2 };
483
502
  var truncate = (value, maxLength = 4096) => {
484
503
  if (value === void 0 || value === null) return value;
@@ -554,18 +573,27 @@ var createHandlerRuntime = (handler, handlerType, logLevel = "info", extraSetupA
554
573
  resolvedParams = await buildParams(handler.config);
555
574
  return resolvedParams;
556
575
  };
557
- const getAuthRuntime = async () => {
576
+ const getAuthRuntime = async (setupCtx) => {
558
577
  if (resolvedAuthRuntime !== null) return resolvedAuthRuntime;
559
- const ssmPath = process.env[ENV_AUTH_SECRET];
560
- if (!ssmPath || !handler.auth) {
578
+ const authOpts = setupCtx && typeof setupCtx === "object" && "auth" in setupCtx ? setupCtx.auth : void 0;
579
+ if (!authOpts?.secret) {
561
580
  resolvedAuthRuntime = void 0;
562
581
  return void 0;
563
582
  }
564
- const values = await getParameters([ssmPath]);
565
- const secret = values.get(ssmPath);
566
- if (!secret) throw new Error(`Auth secret not found at ${ssmPath}`);
567
- const defaultExpires = handler.auth.expiresIn ? toSeconds(handler.auth.expiresIn) : 604800;
568
- resolvedAuthRuntime = createAuthRuntime(secret, defaultExpires);
583
+ const secret = authOpts.secret;
584
+ resolvedAuthHeaderName = authOpts.apiToken?.header;
585
+ const defaultExpires = authOpts.expiresIn ? toSeconds(authOpts.expiresIn) : 604800;
586
+ const apiToken = authOpts.apiToken;
587
+ const cacheTtlSeconds = apiToken?.cacheTtl ? toSeconds(apiToken.cacheTtl) : void 0;
588
+ const rawVerify = apiToken?.verify;
589
+ const wrappedVerify = rawVerify ? (args) => rawVerify(args.value) : void 0;
590
+ resolvedAuthRuntime = createAuthRuntime(
591
+ secret,
592
+ defaultExpires,
593
+ wrappedVerify,
594
+ apiToken?.header,
595
+ cacheTtlSeconds
596
+ );
569
597
  return resolvedAuthRuntime;
570
598
  };
571
599
  const getSetup = async () => {
@@ -573,7 +601,7 @@ var createHandlerRuntime = (handler, handlerType, logLevel = "info", extraSetupA
573
601
  if (handler.setup) {
574
602
  const params = await getParams();
575
603
  const deps = getDeps();
576
- const args = {};
604
+ const args = { enableAuth: (opts) => opts };
577
605
  if (params) args.config = params;
578
606
  if (deps) args.deps = deps;
579
607
  if (handler.static) args.files = staticFiles;
@@ -582,7 +610,8 @@ var createHandlerRuntime = (handler, handlerType, logLevel = "info", extraSetupA
582
610
  }
583
611
  return ctx;
584
612
  };
585
- const commonArgs = async (cookieValue) => {
613
+ let resolvedAuthHeaderName;
614
+ const commonArgs = async (cookieValue, authHeader, headers) => {
586
615
  const args = {};
587
616
  if (handler.setup) args.ctx = await getSetup();
588
617
  const deps = getDeps();
@@ -590,8 +619,14 @@ var createHandlerRuntime = (handler, handlerType, logLevel = "info", extraSetupA
590
619
  const params = await getParams();
591
620
  if (params) args.config = params;
592
621
  if (handler.static) args.files = staticFiles;
593
- const authRuntime = await getAuthRuntime();
594
- if (authRuntime) args.auth = authRuntime.forRequest(cookieValue);
622
+ const authRuntime = await getAuthRuntime(args.ctx);
623
+ if (authRuntime) {
624
+ let finalAuthHeader = authHeader;
625
+ if (finalAuthHeader === void 0 && headers && resolvedAuthHeaderName) {
626
+ finalAuthHeader = headers[resolvedAuthHeaderName] ?? headers[resolvedAuthHeaderName.toLowerCase()] ?? void 0;
627
+ }
628
+ args.auth = await authRuntime.forRequest(cookieValue, finalAuthHeader);
629
+ }
595
630
  return args;
596
631
  };
597
632
  const logExecution = (startTime, input, output) => {