@sylphx/sdk 0.15.1 → 0.15.3

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.
@@ -1,45 +1,6 @@
1
1
  // src/nextjs/middleware.ts
2
2
  import { NextResponse } from "next/server";
3
3
 
4
- // src/constants.ts
5
- var ENV_URL = "SYLPHX_URL";
6
- var ENV_PUBLIC_URL = "NEXT_PUBLIC_SYLPHX_URL";
7
- var ENV_SECRET_URL = "SYLPHX_SECRET_URL";
8
- var SDK_API_PATH = `/v1`;
9
- var DEFAULT_SDK_API_HOST = "api.sylphx.com";
10
- function detectSdkPlatform() {
11
- if (typeof window !== "undefined") return "browser";
12
- const runtimeGlobal = globalThis;
13
- if (typeof runtimeGlobal.EdgeRuntime !== "undefined") return "edge";
14
- return "node";
15
- }
16
- var SDK_PLATFORM = detectSdkPlatform();
17
- var TOKEN_EXPIRY_BUFFER_MS = 3e4;
18
- var SESSION_TOKEN_LIFETIME_SECONDS = 5 * 60;
19
- var SESSION_TOKEN_LIFETIME_MS = SESSION_TOKEN_LIFETIME_SECONDS * 1e3;
20
- var REFRESH_TOKEN_LIFETIME_SECONDS = 30 * 24 * 60 * 60;
21
- var FLAGS_CACHE_TTL_MS = 5 * 60 * 1e3;
22
- var FLAGS_STALE_WHILE_REVALIDATE_MS = 60 * 1e3;
23
- var ANALYTICS_SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
24
- var WEBHOOK_MAX_AGE_MS = 5 * 60 * 1e3;
25
- var WEBHOOK_CLOCK_SKEW_MS = 30 * 1e3;
26
- var PKCE_CODE_TTL_MS = 10 * 60 * 1e3;
27
- var JOBS_DLQ_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
28
- var SESSION_REPLAY_MAX_DURATION_MS = 60 * 60 * 1e3;
29
- var FLAGS_EXPOSURE_DEDUPE_WINDOW_MS = 60 * 60 * 1e3;
30
- var CLICK_ID_EXPIRY_MS = 90 * 24 * 60 * 60 * 1e3;
31
- var STALE_TIME_FREQUENT_MS = 60 * 1e3;
32
- var STALE_TIME_MODERATE_MS = 2 * 60 * 1e3;
33
- var STALE_TIME_STABLE_MS = 5 * 60 * 1e3;
34
- var STALE_TIME_STATS_MS = 30 * 1e3;
35
- var NEW_USER_THRESHOLD_MS = 60 * 1e3;
36
- var STORAGE_MULTIPART_THRESHOLD_BYTES = 5 * 1024 * 1024;
37
- var STORAGE_DEFAULT_MAX_SIZE_BYTES = 5 * 1024 * 1024;
38
- var STORAGE_AVATAR_MAX_SIZE_BYTES = 2 * 1024 * 1024;
39
- var STORAGE_LARGE_MAX_SIZE_BYTES = 10 * 1024 * 1024;
40
- var JWK_CACHE_TTL_MS = 60 * 60 * 1e3;
41
- var ETAG_CACHE_TTL_MS = 5 * 60 * 1e3;
42
-
43
4
  // src/key-validation.ts
44
5
  var PUBLIC_KEY_PATTERN = /^pk_(dev|stg|prod|prev)(?:_[a-z0-9]{12})?_[a-f0-9]{32}$/;
45
6
  var APP_ID_PATTERN = /^(app|pk)_(dev|stg|prod|prev)_[a-z0-9_-]+$/;
@@ -196,6 +157,47 @@ function getCookieNamespace(secretKey) {
196
157
 
197
158
  // src/nextjs/cookies.ts
198
159
  import { cookies } from "next/headers";
160
+
161
+ // src/constants.ts
162
+ var ENV_URL = "SYLPHX_URL";
163
+ var ENV_PUBLIC_URL = "NEXT_PUBLIC_SYLPHX_URL";
164
+ var ENV_SECRET_URL = "SYLPHX_SECRET_URL";
165
+ var SDK_API_PATH = `/v1`;
166
+ var DEFAULT_SDK_API_HOST = "api.sylphx.com";
167
+ function detectSdkPlatform() {
168
+ if (typeof window !== "undefined") return "browser";
169
+ const runtimeGlobal = globalThis;
170
+ if (typeof runtimeGlobal.EdgeRuntime !== "undefined") return "edge";
171
+ return "node";
172
+ }
173
+ var SDK_PLATFORM = detectSdkPlatform();
174
+ var TOKEN_EXPIRY_BUFFER_MS = 3e4;
175
+ var SESSION_TOKEN_LIFETIME_SECONDS = 5 * 60;
176
+ var SESSION_TOKEN_LIFETIME_MS = SESSION_TOKEN_LIFETIME_SECONDS * 1e3;
177
+ var REFRESH_TOKEN_LIFETIME_SECONDS = 30 * 24 * 60 * 60;
178
+ var FLAGS_CACHE_TTL_MS = 5 * 60 * 1e3;
179
+ var FLAGS_STALE_WHILE_REVALIDATE_MS = 60 * 1e3;
180
+ var ANALYTICS_SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
181
+ var WEBHOOK_MAX_AGE_MS = 5 * 60 * 1e3;
182
+ var WEBHOOK_CLOCK_SKEW_MS = 30 * 1e3;
183
+ var PKCE_CODE_TTL_MS = 10 * 60 * 1e3;
184
+ var JOBS_DLQ_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
185
+ var SESSION_REPLAY_MAX_DURATION_MS = 60 * 60 * 1e3;
186
+ var FLAGS_EXPOSURE_DEDUPE_WINDOW_MS = 60 * 60 * 1e3;
187
+ var CLICK_ID_EXPIRY_MS = 90 * 24 * 60 * 60 * 1e3;
188
+ var STALE_TIME_FREQUENT_MS = 60 * 1e3;
189
+ var STALE_TIME_MODERATE_MS = 2 * 60 * 1e3;
190
+ var STALE_TIME_STABLE_MS = 5 * 60 * 1e3;
191
+ var STALE_TIME_STATS_MS = 30 * 1e3;
192
+ var NEW_USER_THRESHOLD_MS = 60 * 1e3;
193
+ var STORAGE_MULTIPART_THRESHOLD_BYTES = 5 * 1024 * 1024;
194
+ var STORAGE_DEFAULT_MAX_SIZE_BYTES = 5 * 1024 * 1024;
195
+ var STORAGE_AVATAR_MAX_SIZE_BYTES = 2 * 1024 * 1024;
196
+ var STORAGE_LARGE_MAX_SIZE_BYTES = 10 * 1024 * 1024;
197
+ var JWK_CACHE_TTL_MS = 60 * 60 * 1e3;
198
+ var ETAG_CACHE_TTL_MS = 5 * 60 * 1e3;
199
+
200
+ // src/nextjs/cookies.ts
199
201
  function getCookieNames(namespace) {
200
202
  return {
201
203
  /** HttpOnly JWT access token (5 min) */
@@ -230,6 +232,26 @@ var ACTIVE_ORG_COOKIE_OPTIONS = {
230
232
  ...SECURE_COOKIE_OPTIONS,
231
233
  httpOnly: true
232
234
  };
235
+ function decodeCookieValue(value) {
236
+ try {
237
+ return decodeURIComponent(value);
238
+ } catch {
239
+ return value;
240
+ }
241
+ }
242
+ function readCookieValueFromHeader(cookieHeader, name) {
243
+ if (!cookieHeader) return null;
244
+ let value = null;
245
+ for (const cookie of cookieHeader.split(";")) {
246
+ const trimmed = cookie.trim();
247
+ const eq = trimmed.indexOf("=");
248
+ if (eq === -1) continue;
249
+ if (trimmed.slice(0, eq) === name) {
250
+ value = decodeCookieValue(trimmed.slice(eq + 1));
251
+ }
252
+ }
253
+ return value;
254
+ }
233
255
  async function getAuthCookies(namespace) {
234
256
  const cookieStore = await cookies();
235
257
  const names = getCookieNames(namespace);
@@ -326,6 +348,163 @@ function parseUserCookie(value) {
326
348
  }
327
349
  }
328
350
 
351
+ // src/nextjs/middleware-helpers.ts
352
+ var OAUTH_PKCE_TTL_SECONDS = 10 * 60;
353
+ var OAUTH_PKCE_TTL_MS = OAUTH_PKCE_TTL_SECONDS * 1e3;
354
+ var DEFAULT_BAAS_PREFIX = "/sylphx";
355
+ var BAAS_PROXY_AUTH_REQUIRED_PATHS = ["/challenge/", "/security/"];
356
+ var BAAS_PROXY_PUBLIC_PATHS = ["/app"];
357
+ var BODYLESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
358
+ var RESPONSE_HEADER_ALLOWLIST = [
359
+ "cache-control",
360
+ "content-language",
361
+ "content-type",
362
+ "etag",
363
+ "expires",
364
+ "last-modified",
365
+ "retry-after"
366
+ ];
367
+ function isTokenResponse(data) {
368
+ return typeof data === "object" && data !== null && "accessToken" in data && "refreshToken" in data && "user" in data && typeof data.accessToken === "string" && typeof data.refreshToken === "string";
369
+ }
370
+ function decodeJwtPayload(token) {
371
+ try {
372
+ const parts = token.split(".");
373
+ if (parts.length !== 3) return null;
374
+ const payload = parts[1];
375
+ const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
376
+ const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
377
+ const jsonPayload = atob(padded);
378
+ return JSON.parse(jsonPayload);
379
+ } catch {
380
+ return null;
381
+ }
382
+ }
383
+ function isTokenExpired(token) {
384
+ const payload = decodeJwtPayload(token);
385
+ if (!payload?.exp) return true;
386
+ return payload.exp * 1e3 < Date.now() + TOKEN_EXPIRY_BUFFER_MS;
387
+ }
388
+ function matchesPattern(pathname, pattern) {
389
+ if (pattern === pathname) return true;
390
+ if (pattern.endsWith("/*")) {
391
+ const base = pattern.slice(0, -2);
392
+ return pathname === base || pathname.startsWith(`${base}/`);
393
+ }
394
+ if (pattern.endsWith("/**")) {
395
+ const base = pattern.slice(0, -3);
396
+ return pathname === base || pathname.startsWith(`${base}/`);
397
+ }
398
+ return false;
399
+ }
400
+ function matchesAny(pathname, patterns) {
401
+ return patterns.some((p) => matchesPattern(pathname, p));
402
+ }
403
+ function normalizeRoutePrefix(prefix) {
404
+ const normalized = prefix.trim().replace(/\/+$/u, "");
405
+ return normalized.startsWith("/") ? normalized : `/${normalized}`;
406
+ }
407
+ function stripRoutePrefix(pathname, prefix) {
408
+ if (pathname === prefix) return "/";
409
+ if (!pathname.startsWith(`${prefix}/`)) return null;
410
+ return pathname.slice(prefix.length);
411
+ }
412
+ function isPublicBaasProxyPath(pathname) {
413
+ return BAAS_PROXY_PUBLIC_PATHS.some((path) => pathname === path);
414
+ }
415
+ function isAuthenticatedBaasProxyPath(pathname) {
416
+ return BAAS_PROXY_AUTH_REQUIRED_PATHS.some((prefix) => pathname.startsWith(prefix));
417
+ }
418
+ function isAllowedBaasProxyPath(pathname) {
419
+ return isPublicBaasProxyPath(pathname) || isAuthenticatedBaasProxyPath(pathname);
420
+ }
421
+ function copyRequestHeader(source, target, name) {
422
+ const value = source.get(name);
423
+ if (value) target.set(name, value);
424
+ }
425
+ function buildUpstreamProxyHeaders(request, ctx, sessionToken) {
426
+ const headers = new Headers();
427
+ copyRequestHeader(request.headers, headers, "accept");
428
+ copyRequestHeader(request.headers, headers, "content-type");
429
+ copyRequestHeader(request.headers, headers, "user-agent");
430
+ copyRequestHeader(request.headers, headers, "x-correlation-id");
431
+ headers.set("x-app-secret", ctx.secretKey);
432
+ if (sessionToken) headers.set("authorization", `Bearer ${sessionToken}`);
433
+ return headers;
434
+ }
435
+ function copyResponseHeaders(source) {
436
+ const headers = new Headers();
437
+ for (const name of RESPONSE_HEADER_ALLOWLIST) {
438
+ const value = source.get(name);
439
+ if (value) headers.set(name, value);
440
+ }
441
+ return headers;
442
+ }
443
+ function requestPathWithSearch(request) {
444
+ const { pathname, search } = request.nextUrl;
445
+ return `${pathname}${search}`;
446
+ }
447
+ function isSafeRelativeRedirectPath(value) {
448
+ return typeof value === "string" && value.startsWith("/") && !value.startsWith("//");
449
+ }
450
+ function resolveSafeRelativeRedirectPath(value, fallback) {
451
+ if (isSafeRelativeRedirectPath(value)) return value;
452
+ if (isSafeRelativeRedirectPath(fallback)) return fallback;
453
+ return "/";
454
+ }
455
+ function resolveSameOriginUrl(request, value, fallbackPath) {
456
+ if (!value) return new URL(fallbackPath, request.url).toString();
457
+ if (isSafeRelativeRedirectPath(value)) {
458
+ const url = new URL(value, request.url);
459
+ if (url.hash) return null;
460
+ return url.toString();
461
+ }
462
+ try {
463
+ const url = new URL(value);
464
+ if (url.origin !== new URL(request.url).origin) return null;
465
+ if (url.hash) return null;
466
+ return url.toString();
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
471
+ function normalizeAppUrl(value) {
472
+ if (!value?.trim()) return null;
473
+ try {
474
+ const url = new URL(value);
475
+ return url.origin;
476
+ } catch {
477
+ return null;
478
+ }
479
+ }
480
+ function resolveOAuthCallbackUrl(request, ctx) {
481
+ const origin = ctx.config.appUrl ?? new URL(request.url).origin;
482
+ return new URL(`${ctx.config.authPrefix}/callback`, origin);
483
+ }
484
+ function bytesToBase64Url(bytes) {
485
+ let binary = "";
486
+ for (const byte of bytes) binary += String.fromCharCode(byte);
487
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
488
+ }
489
+ function randomBase64Url(byteLength) {
490
+ const bytes = new Uint8Array(byteLength);
491
+ crypto.getRandomValues(bytes);
492
+ return bytesToBase64Url(bytes);
493
+ }
494
+ async function sha256Base64Url(value) {
495
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
496
+ return bytesToBase64Url(new Uint8Array(digest));
497
+ }
498
+ async function parseJsonObject(request) {
499
+ try {
500
+ const body = await request.json();
501
+ if (typeof body === "object" && body !== null && !Array.isArray(body)) return body;
502
+ return null;
503
+ } catch {
504
+ return null;
505
+ }
506
+ }
507
+
329
508
  // src/connection-url.ts
330
509
  var SYLPHX_PROTOCOL = "sylphx:";
331
510
  var DEFAULT_VERSION = "v1";
@@ -482,161 +661,6 @@ function resolveNextjsPublishableKey(options) {
482
661
  }
483
662
 
484
663
  // src/nextjs/middleware.ts
485
- var OAUTH_PKCE_TTL_SECONDS = 10 * 60;
486
- var OAUTH_PKCE_TTL_MS = OAUTH_PKCE_TTL_SECONDS * 1e3;
487
- var DEFAULT_BAAS_PREFIX = "/sylphx";
488
- var BAAS_PROXY_AUTH_REQUIRED_PATHS = ["/challenge/", "/security/"];
489
- var BAAS_PROXY_PUBLIC_PATHS = ["/app"];
490
- var BODYLESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
491
- var RESPONSE_HEADER_ALLOWLIST = [
492
- "cache-control",
493
- "content-language",
494
- "content-type",
495
- "etag",
496
- "expires",
497
- "last-modified",
498
- "retry-after"
499
- ];
500
- function isTokenResponse(data) {
501
- return typeof data === "object" && data !== null && "accessToken" in data && "refreshToken" in data && "user" in data && typeof data.accessToken === "string" && typeof data.refreshToken === "string";
502
- }
503
- function decodeJwtPayload(token) {
504
- try {
505
- const parts = token.split(".");
506
- if (parts.length !== 3) return null;
507
- const payload = parts[1];
508
- const base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
509
- const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
510
- const jsonPayload = atob(padded);
511
- return JSON.parse(jsonPayload);
512
- } catch {
513
- return null;
514
- }
515
- }
516
- function isTokenExpired(token) {
517
- const payload = decodeJwtPayload(token);
518
- if (!payload?.exp) return true;
519
- return payload.exp * 1e3 < Date.now() + TOKEN_EXPIRY_BUFFER_MS;
520
- }
521
- function matchesPattern(pathname, pattern) {
522
- if (pattern === pathname) return true;
523
- if (pattern.endsWith("/*")) {
524
- const base = pattern.slice(0, -2);
525
- return pathname === base || pathname.startsWith(`${base}/`);
526
- }
527
- if (pattern.endsWith("/**")) {
528
- const base = pattern.slice(0, -3);
529
- return pathname === base || pathname.startsWith(`${base}/`);
530
- }
531
- return false;
532
- }
533
- function matchesAny(pathname, patterns) {
534
- return patterns.some((p) => matchesPattern(pathname, p));
535
- }
536
- function normalizeRoutePrefix(prefix) {
537
- const normalized = prefix.trim().replace(/\/+$/u, "");
538
- return normalized.startsWith("/") ? normalized : `/${normalized}`;
539
- }
540
- function stripRoutePrefix(pathname, prefix) {
541
- if (pathname === prefix) return "/";
542
- if (!pathname.startsWith(`${prefix}/`)) return null;
543
- return pathname.slice(prefix.length);
544
- }
545
- function isPublicBaasProxyPath(pathname) {
546
- return BAAS_PROXY_PUBLIC_PATHS.some((path) => pathname === path);
547
- }
548
- function isAuthenticatedBaasProxyPath(pathname) {
549
- return BAAS_PROXY_AUTH_REQUIRED_PATHS.some((prefix) => pathname.startsWith(prefix));
550
- }
551
- function isAllowedBaasProxyPath(pathname) {
552
- return isPublicBaasProxyPath(pathname) || isAuthenticatedBaasProxyPath(pathname);
553
- }
554
- function copyRequestHeader(source, target, name) {
555
- const value = source.get(name);
556
- if (value) target.set(name, value);
557
- }
558
- function buildUpstreamProxyHeaders(request, ctx, sessionToken) {
559
- const headers = new Headers();
560
- copyRequestHeader(request.headers, headers, "accept");
561
- copyRequestHeader(request.headers, headers, "content-type");
562
- copyRequestHeader(request.headers, headers, "user-agent");
563
- copyRequestHeader(request.headers, headers, "x-correlation-id");
564
- headers.set("x-app-secret", ctx.secretKey);
565
- if (sessionToken) headers.set("authorization", `Bearer ${sessionToken}`);
566
- return headers;
567
- }
568
- function copyResponseHeaders(source) {
569
- const headers = new Headers();
570
- for (const name of RESPONSE_HEADER_ALLOWLIST) {
571
- const value = source.get(name);
572
- if (value) headers.set(name, value);
573
- }
574
- return headers;
575
- }
576
- function requestPathWithSearch(request) {
577
- const { pathname, search } = request.nextUrl;
578
- return `${pathname}${search}`;
579
- }
580
- function isSafeRelativeRedirectPath(value) {
581
- return typeof value === "string" && value.startsWith("/") && !value.startsWith("//");
582
- }
583
- function resolveSafeRelativeRedirectPath(value, fallback) {
584
- if (isSafeRelativeRedirectPath(value)) return value;
585
- if (isSafeRelativeRedirectPath(fallback)) return fallback;
586
- return "/";
587
- }
588
- function resolveSameOriginUrl(request, value, fallbackPath) {
589
- if (!value) return new URL(fallbackPath, request.url).toString();
590
- if (isSafeRelativeRedirectPath(value)) {
591
- const url = new URL(value, request.url);
592
- if (url.hash) return null;
593
- return url.toString();
594
- }
595
- try {
596
- const url = new URL(value);
597
- if (url.origin !== new URL(request.url).origin) return null;
598
- if (url.hash) return null;
599
- return url.toString();
600
- } catch {
601
- return null;
602
- }
603
- }
604
- function normalizeAppUrl(value) {
605
- if (!value?.trim()) return null;
606
- try {
607
- const url = new URL(value);
608
- return url.origin;
609
- } catch {
610
- return null;
611
- }
612
- }
613
- function resolveOAuthCallbackUrl(request, ctx) {
614
- const origin = ctx.config.appUrl ?? new URL(request.url).origin;
615
- return new URL(`${ctx.config.authPrefix}/callback`, origin);
616
- }
617
- function bytesToBase64Url(bytes) {
618
- let binary = "";
619
- for (const byte of bytes) binary += String.fromCharCode(byte);
620
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
621
- }
622
- function randomBase64Url(byteLength) {
623
- const bytes = new Uint8Array(byteLength);
624
- crypto.getRandomValues(bytes);
625
- return bytesToBase64Url(bytes);
626
- }
627
- async function sha256Base64Url(value) {
628
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
629
- return bytesToBase64Url(new Uint8Array(digest));
630
- }
631
- async function parseJsonObject(request) {
632
- try {
633
- const body = await request.json();
634
- if (typeof body === "object" && body !== null && !Array.isArray(body)) return body;
635
- return null;
636
- } catch {
637
- return null;
638
- }
639
- }
640
664
  function getOAuthPkceCookieName(ctx) {
641
665
  return `__${ctx.namespace}_oauth_pkce`;
642
666
  }
@@ -670,6 +694,19 @@ function clearOAuthPkceCookie(response, ctx) {
670
694
  path: ctx.config.authPrefix
671
695
  });
672
696
  }
697
+ function readRequestCookieValue(request, name) {
698
+ const values = request.cookies.getAll(name);
699
+ if (values.length > 0) {
700
+ const value = values[values.length - 1]?.value;
701
+ return value === void 0 ? void 0 : decodeCookieValue(value);
702
+ }
703
+ const cookie = request.cookies.get(name);
704
+ if (cookie) return decodeCookieValue(cookie.value);
705
+ return readCookieValueFromHeader(request.headers.get("cookie"), name) ?? void 0;
706
+ }
707
+ function hasRequestCookie(request, name) {
708
+ return readRequestCookieValue(request, name) !== void 0;
709
+ }
673
710
  function isTwoFactorLoginResponse(data) {
674
711
  return typeof data === "object" && data !== null && data.requiresTwoFactor === true && typeof data.userId === "string";
675
712
  }
@@ -702,7 +739,7 @@ function setRestoredSessionCookies(response, ctx, restored) {
702
739
  }
703
740
  }
704
741
  async function refreshSessionFromCookie(request, ctx, previousSessionToken) {
705
- const refreshToken = request.cookies.get(ctx.cookieNames.REFRESH)?.value;
742
+ const refreshToken = readRequestCookieValue(request, ctx.cookieNames.REFRESH);
706
743
  if (!refreshToken) return null;
707
744
  const refreshedTokens = await refreshTokens(refreshToken, ctx);
708
745
  if (!refreshedTokens) return null;
@@ -799,8 +836,8 @@ async function handleSession(request, ctx) {
799
836
  if (request.method !== "GET") {
800
837
  return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
801
838
  }
802
- const sessionToken = request.cookies.get(ctx.cookieNames.SESSION)?.value;
803
- const userCookie = parseUserCookie2(request.cookies.get(ctx.cookieNames.USER)?.value);
839
+ const sessionToken = readRequestCookieValue(request, ctx.cookieNames.SESSION);
840
+ const userCookie = parseUserCookie2(readRequestCookieValue(request, ctx.cookieNames.USER));
804
841
  if (sessionToken && !isTokenExpired(sessionToken) && userCookie?.user) {
805
842
  return NextResponse.json(sessionMetadataBody(sessionToken, userCookie.user));
806
843
  }
@@ -813,7 +850,7 @@ async function handleSession(request, ctx) {
813
850
  return response2;
814
851
  }
815
852
  const response = NextResponse.json({ success: true, session: null, user: null });
816
- if (sessionToken || request.cookies.has(ctx.cookieNames.REFRESH) || userCookie) {
853
+ if (sessionToken || hasRequestCookie(request, ctx.cookieNames.REFRESH) || userCookie) {
817
854
  clearAuthCookiesMiddleware(response, ctx.namespace);
818
855
  }
819
856
  return response;
@@ -999,7 +1036,7 @@ async function handleCallback(request, ctx) {
999
1036
  }
1000
1037
  async function handleSignOut(request, ctx) {
1001
1038
  ctx.log("Signout");
1002
- const refreshToken = request.cookies.get(ctx.cookieNames.REFRESH)?.value;
1039
+ const refreshToken = readRequestCookieValue(request, ctx.cookieNames.REFRESH);
1003
1040
  if (refreshToken) {
1004
1041
  try {
1005
1042
  await fetch(`${ctx.platformUrl}/v1/auth/revoke`, {
@@ -1021,7 +1058,7 @@ async function handleSignOut(request, ctx) {
1021
1058
  }
1022
1059
  async function handleToken(request, ctx) {
1023
1060
  ctx.log("Token request");
1024
- const sessionToken = request.cookies.get(ctx.cookieNames.SESSION)?.value;
1061
+ const sessionToken = readRequestCookieValue(request, ctx.cookieNames.SESSION);
1025
1062
  if (sessionToken && !isTokenExpired(sessionToken)) {
1026
1063
  ctx.log("Token returned");
1027
1064
  return NextResponse.json({ accessToken: sessionToken });
@@ -1038,7 +1075,7 @@ async function handleToken(request, ctx) {
1038
1075
  { error: sessionToken ? "Session expired" : "Not authenticated", accessToken: null },
1039
1076
  { status: 401 }
1040
1077
  );
1041
- if (sessionToken || request.cookies.has(ctx.cookieNames.REFRESH)) {
1078
+ if (sessionToken || hasRequestCookie(request, ctx.cookieNames.REFRESH)) {
1042
1079
  clearAuthCookiesMiddleware(response, ctx.namespace);
1043
1080
  }
1044
1081
  return response;
@@ -1071,17 +1108,10 @@ function parseUserCookie2(value) {
1071
1108
  return null;
1072
1109
  }
1073
1110
  }
1074
- function decodeCookieValue(value) {
1075
- try {
1076
- return decodeURIComponent(value);
1077
- } catch {
1078
- return value;
1079
- }
1080
- }
1081
1111
  function readFirstCookieValue(request, names) {
1082
1112
  for (const name of names) {
1083
- const value = request.cookies.get(name)?.value;
1084
- if (value) return decodeCookieValue(value);
1113
+ const value = readRequestCookieValue(request, name);
1114
+ if (value) return value;
1085
1115
  }
1086
1116
  return null;
1087
1117
  }
@@ -1214,7 +1244,7 @@ async function handleSwitchOrg(request, ctx) {
1214
1244
  if (request.method !== "POST") {
1215
1245
  return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
1216
1246
  }
1217
- const currentSessionToken = request.cookies.get(ctx.cookieNames.SESSION)?.value;
1247
+ const currentSessionToken = readRequestCookieValue(request, ctx.cookieNames.SESSION);
1218
1248
  let sessionToken = currentSessionToken && !isTokenExpired(currentSessionToken) ? currentSessionToken : null;
1219
1249
  let restoredBaseSession = null;
1220
1250
  if (!sessionToken) {
@@ -1226,7 +1256,7 @@ async function handleSwitchOrg(request, ctx) {
1226
1256
  { error: "Not authenticated", accessToken: null },
1227
1257
  { status: 401 }
1228
1258
  );
1229
- if (currentSessionToken || request.cookies.has(ctx.cookieNames.REFRESH)) {
1259
+ if (currentSessionToken || hasRequestCookie(request, ctx.cookieNames.REFRESH)) {
1230
1260
  clearAuthCookiesMiddleware(response, ctx.namespace);
1231
1261
  }
1232
1262
  return response;
@@ -1281,7 +1311,7 @@ async function handleSwitchOrg(request, ctx) {
1281
1311
  ...SECURE_COOKIE_OPTIONS,
1282
1312
  maxAge: expiresIn
1283
1313
  });
1284
- const existingUser = parseUserCookie2(request.cookies.get(ctx.cookieNames.USER)?.value);
1314
+ const existingUser = parseUserCookie2(readRequestCookieValue(request, ctx.cookieNames.USER));
1285
1315
  const user = data.user ?? existingUser?.user;
1286
1316
  if (user) {
1287
1317
  response.cookies.set(
@@ -1506,8 +1536,8 @@ function createSylphxMiddleware(userConfig = {}) {
1506
1536
  if (pathname === `${config.authPrefix}/switch-org`) {
1507
1537
  return handleSwitchOrg(request, ctx);
1508
1538
  }
1509
- const sessionToken = request.cookies.get(cookieNames.SESSION)?.value;
1510
- const refreshToken = request.cookies.get(cookieNames.REFRESH)?.value;
1539
+ const sessionToken = readRequestCookieValue(request, cookieNames.SESSION);
1540
+ const refreshToken = readRequestCookieValue(request, cookieNames.REFRESH);
1511
1541
  const hasValidSession = sessionToken && !isTokenExpired(sessionToken);
1512
1542
  const response = NextResponse.next({ request: { headers: request.headers } });
1513
1543
  let isAuthenticated = hasValidSession;
@@ -3028,6 +3058,7 @@ export {
3028
3058
  createSylphxMiddleware,
3029
3059
  currentUser,
3030
3060
  currentUserId,
3061
+ decodeCookieValue,
3031
3062
  decodeUserId,
3032
3063
  encodeUserId,
3033
3064
  getAuthCookies,
@@ -3039,6 +3070,7 @@ export {
3039
3070
  hasRefreshToken,
3040
3071
  isSessionExpired,
3041
3072
  parseUserCookie,
3073
+ readCookieValueFromHeader,
3042
3074
  setAuthCookies,
3043
3075
  setAuthCookiesMiddleware,
3044
3076
  signOut,