@payez/next-mvp 4.5.3 → 4.5.4
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/middleware/create-middleware.js +16 -2
- package/package.json +1042 -1042
- package/src/middleware/create-middleware.ts +16 -2
|
@@ -575,7 +575,16 @@ async function checkViability(request, endpoint, log, revocationFailMode) {
|
|
|
575
575
|
// booleans for unknown/not_configured. The booleans are read ONLY when
|
|
576
576
|
// revocationStatus is ABSENT (idealresume.online's older boolean route).
|
|
577
577
|
sessionStatus.forceInvalid = decideForceInvalid(data, revocationFailMode);
|
|
578
|
-
|
|
578
|
+
// PAY-2216: a STALE session - the cookie resolved to a token, but no store holds the session - used to set
|
|
579
|
+
// pointer.exists=false, so makeAuthDecision took no_session (login, cookie NOT cleared) and its stale_session
|
|
580
|
+
// arm (clearCookies) was unreachable: a dead cookie lingered and re-ran viability on every request.
|
|
581
|
+
// Stale is a POSITIVE signal and needs ALL of: this 2xx read, exists === false, a sessionTokenId (every
|
|
582
|
+
// producer sets it only when a cookie resolved to a token: routes/auth/viability.ts, api-handlers/session/
|
|
583
|
+
// viability.ts, refresh-viability.ts 'session_not_found'), and a session cookie on THIS request (plain or
|
|
584
|
+
// __Secure-). A FAILED read never gets here (exists=null -> service_error, PAY-2147); a store error throws
|
|
585
|
+
// inside every producer and answers 5xx or 'unknown' WITHOUT a sessionTokenId; no cookie -> no_session.
|
|
586
|
+
const stale = sessionStatus.exists === false && !!data.sessionTokenId && hasSessionCookie(request);
|
|
587
|
+
sessionPointer.exists = stale ? true : (sessionStatus.exists ?? false);
|
|
579
588
|
sessionPointer.sessionTokenId = data.sessionTokenId ?? null;
|
|
580
589
|
sessionPointer.expired = data.accessTokenExpired || false;
|
|
581
590
|
sessionPointer.hasRefreshToken = data.hasRefreshToken ?? data.canRefresh ?? false;
|
|
@@ -620,7 +629,12 @@ const RBAC_EXEMPT_PATHS = ['/error', '/unauthorized', '/service-unavailable'];
|
|
|
620
629
|
/** Handle 'allow' decision - run RBAC if enabled */
|
|
621
630
|
async function handleAllow(request, pathname, sessionPointer, sessionStatus, rbacExemptPaths = []) {
|
|
622
631
|
const isPublic = (0, route_config_1.isUnauthenticatedRoute)(pathname);
|
|
623
|
-
|
|
632
|
+
// PAY-2216: RBAC needs a session that viability CONFIRMED. A stale /api request (pointer.exists only says the
|
|
633
|
+
// cookie is present, status.exists is false) is allowed through so the route handler answers its own 401 - not an
|
|
634
|
+
// RBAC 401 here. TRUTHY, not `=== true` (NightHawk 71960): status.exists carries the producer's JSON value as-is,
|
|
635
|
+
// and a consumer route may answer authenticated: 1 / "true"; `=== true` skipped RBAC for those healthy sessions
|
|
636
|
+
// (fail-OPEN). Truthy keeps 4.5.3's RBAC coverage exactly and still excludes stale (false) and a failed read (null).
|
|
637
|
+
if ((0, rbac_check_1.isRBACEnabled)() && !isPublic && sessionPointer.exists && sessionStatus.exists) {
|
|
624
638
|
// Skip RBAC for error/fallback pages (prevent redirect loops) and app-configured exempt paths
|
|
625
639
|
if (RBAC_EXEMPT_PATHS.some(p => pathname.startsWith(p)) ||
|
|
626
640
|
rbacExemptPaths.some(p => pathname.startsWith(p))) {
|