@payez/next-mvp 4.11.0 → 4.12.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.
- package/CHANGELOG.md +13 -0
- package/dist/api-handlers/account/recovery/forward.js +2 -1
- package/dist/api-handlers/account/recovery/initiate.js +2 -1
- package/dist/api-handlers/account/reset-password.js +2 -1
- package/dist/api-handlers/account/send-code.js +2 -1
- package/dist/api-handlers/account/update-phone.js +2 -1
- package/dist/api-handlers/account/validate-password.js +2 -1
- package/dist/api-handlers/account/verify-email.js +2 -1
- package/dist/api-handlers/account/verify-sms.js +2 -1
- package/dist/api-handlers/anon/preferences.js +3 -2
- package/dist/api-handlers/auth/credential-login-email-code.js +3 -2
- package/dist/api-handlers/auth/credential-login.js +6 -5
- package/dist/api-handlers/auth/refresh.js +2 -1
- package/dist/api-handlers/auth/signout.js +43 -6
- package/dist/api-handlers/mfa/backup-code-verify.js +2 -1
- package/dist/api-handlers/mfa/totp-verify.js +2 -1
- package/dist/api-handlers/session/refresh-viability.js +3 -2
- package/dist/api-handlers/session/viability.js +2 -1
- package/dist/auth/better-auth.js +7 -6
- package/dist/auth/idp-oauth.js +4 -2
- package/dist/auth/utils/idp-client.js +5 -4
- package/dist/auth/utils/token-utils.js +4 -3
- package/dist/config/logger.js +2 -1
- package/dist/config/logging-config.js +4 -3
- package/dist/config/vibe-log-transport.js +2 -1
- package/dist/lib/ensure-fresh-access-token.js +2 -1
- package/dist/lib/geolocation.js +5 -22
- package/dist/lib/idp-client-config.js +4 -3
- package/dist/lib/idp-fetch.d.ts +11 -0
- package/dist/lib/idp-fetch.js +3 -1
- package/dist/lib/idp-logout.d.ts +10 -0
- package/dist/lib/idp-logout.js +73 -1
- package/dist/lib/jwt-decode-client.js +2 -1
- package/dist/lib/jwt-decode.js +2 -1
- package/dist/lib/log-safe.d.ts +19 -0
- package/dist/lib/log-safe.js +32 -0
- package/dist/lib/redis.js +2 -1
- package/dist/lib/safe-error-response.d.ts +5 -1
- package/dist/lib/safe-error-response.js +7 -2
- package/dist/lib/session-store.js +2 -1
- package/dist/lib/site-logger.d.ts +2 -8
- package/dist/lib/site-logger.js +11 -5
- package/dist/lib/standardized-client-api.js +3 -2
- package/dist/lib/token-lifecycle.js +3 -2
- package/dist/middleware/create-middleware.js +2 -1
- package/dist/middleware/rbac-check.d.ts +0 -13
- package/dist/middleware/rbac-check.js +6 -5
- package/dist/routes/auth/logout.js +6 -2
- package/dist/routes/auth/settings.js +2 -1
- package/dist/server/auth-guard.js +4 -3
- package/dist/server/auth.js +5 -9
- package/dist/server/decode-session.js +3 -2
- package/dist/server/with-auth.js +2 -1
- package/package.json +1 -1
- package/src/api-handlers/account/recovery/forward.ts +2 -1
- package/src/api-handlers/account/recovery/initiate.ts +2 -1
- package/src/api-handlers/account/reset-password.ts +2 -1
- package/src/api-handlers/account/send-code.ts +2 -1
- package/src/api-handlers/account/update-phone.ts +2 -1
- package/src/api-handlers/account/validate-password.ts +2 -1
- package/src/api-handlers/account/verify-email.ts +2 -1
- package/src/api-handlers/account/verify-sms.ts +2 -1
- package/src/api-handlers/anon/preferences.ts +3 -2
- package/src/api-handlers/auth/credential-login-email-code.ts +3 -2
- package/src/api-handlers/auth/credential-login.ts +6 -5
- package/src/api-handlers/auth/refresh.ts +2 -1
- package/src/api-handlers/auth/signout.ts +54 -7
- package/src/api-handlers/mfa/backup-code-verify.ts +2 -1
- package/src/api-handlers/mfa/totp-verify.ts +2 -1
- package/src/api-handlers/session/refresh-viability.ts +3 -2
- package/src/api-handlers/session/viability.ts +2 -1
- package/src/auth/better-auth.ts +7 -6
- package/src/auth/idp-oauth.ts +7 -2
- package/src/auth/utils/idp-client.ts +5 -4
- package/src/auth/utils/token-utils.ts +4 -3
- package/src/config/logger.ts +2 -1
- package/src/config/logging-config.ts +4 -3
- package/src/config/vibe-log-transport.ts +2 -1
- package/src/lib/ensure-fresh-access-token.ts +2 -1
- package/src/lib/geolocation.ts +5 -4
- package/src/lib/idp-client-config.ts +4 -3
- package/src/lib/idp-fetch.ts +11 -1
- package/src/lib/idp-logout.ts +36 -1
- package/src/lib/jwt-decode-client.ts +3 -1
- package/src/lib/jwt-decode.ts +2 -1
- package/src/lib/log-safe.ts +30 -0
- package/src/lib/redis.ts +2 -1
- package/src/lib/safe-error-response.ts +7 -2
- package/src/lib/session-store.ts +2 -1
- package/src/lib/site-logger.ts +13 -7
- package/src/lib/standardized-client-api.ts +3 -2
- package/src/lib/token-lifecycle.ts +3 -2
- package/src/middleware/create-middleware.ts +2 -1
- package/src/middleware/rbac-check.ts +2 -1
- package/src/routes/auth/logout.ts +9 -2
- package/src/routes/auth/settings.ts +2 -1
- package/src/server/auth-guard.ts +4 -3
- package/src/server/auth.ts +5 -10
- package/src/server/decode-session.ts +3 -2
- package/src/server/with-auth.ts +2 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// ========================================================================================
|
|
10
10
|
|
|
11
11
|
import { authClient } from '../client/better-auth-client';
|
|
12
|
+
import { errForLog } from './log-safe';
|
|
12
13
|
|
|
13
14
|
/** Unwrap Better Auth getSession() to a flat session-like object for backward compat */
|
|
14
15
|
async function getSession(): Promise<any> {
|
|
@@ -147,7 +148,7 @@ function scheduleLoginRedirect(isImmediate = false) {
|
|
|
147
148
|
console.warn(`🔄 Redirecting to login with return URL: ${returnUrl}`);
|
|
148
149
|
window.location.href = `/account-auth/login?returnUrl=${returnUrl}`;
|
|
149
150
|
} catch (error) {
|
|
150
|
-
console.error('❌ Error during login redirect:', error);
|
|
151
|
+
console.error('❌ Error during login redirect:', errForLog(error));
|
|
151
152
|
// Final fallback
|
|
152
153
|
try {
|
|
153
154
|
window.location.href = '/account-auth/login';
|
|
@@ -721,7 +722,7 @@ class StandardizedClientApiService {
|
|
|
721
722
|
}
|
|
722
723
|
|
|
723
724
|
// Wrap unknown errors as network errors
|
|
724
|
-
console.error('❌ API request failed:', error);
|
|
725
|
+
console.error('❌ API request failed:', errForLog(error));
|
|
725
726
|
throw new ApiNetworkError(
|
|
726
727
|
error instanceof Error ? error.message : 'Network error',
|
|
727
728
|
0,
|
|
@@ -27,6 +27,7 @@ import { getRedis } from './redis';
|
|
|
27
27
|
import { getAppSlug } from './app-slug';
|
|
28
28
|
import { tokenLogId } from './token-log-id';
|
|
29
29
|
import { REFRESH_WINDOW_MS } from './refresh-window';
|
|
30
|
+
import { errForLog } from './log-safe';
|
|
30
31
|
|
|
31
32
|
// "needs refresh" threshold: THE one freshness window (lib/refresh-window), the same value the refresh route, ensureFreshAccessToken and idp-fetch use.
|
|
32
33
|
const REFRESH_THRESHOLD_MS = REFRESH_WINDOW_MS;
|
|
@@ -434,7 +435,7 @@ export async function ensureFreshToken(
|
|
|
434
435
|
}
|
|
435
436
|
} catch (e) {
|
|
436
437
|
// If we can't decode, proceed with normal logic
|
|
437
|
-
console.warn('[TOKEN_LIFECYCLE] Could not validate JWT exp claim:', e);
|
|
438
|
+
console.warn('[TOKEN_LIFECYCLE] Could not validate JWT exp claim:', errForLog(e));
|
|
438
439
|
}
|
|
439
440
|
}
|
|
440
441
|
|
|
@@ -512,7 +513,7 @@ export async function ensureFreshToken(
|
|
|
512
513
|
sessionData,
|
|
513
514
|
};
|
|
514
515
|
} catch (error) {
|
|
515
|
-
console.error('[TOKEN_LIFECYCLE] Error:', error);
|
|
516
|
+
console.error('[TOKEN_LIFECYCLE] Error:', errForLog(error));
|
|
516
517
|
return {
|
|
517
518
|
success: false,
|
|
518
519
|
error: 'NO_SESSION',
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
resetSecret,
|
|
33
33
|
signedResetHref,
|
|
34
34
|
} from '../auth/session-reset-link';
|
|
35
|
+
import { errForLog } from '../lib/log-safe';
|
|
35
36
|
|
|
36
37
|
// =============================================================================
|
|
37
38
|
// TYPES
|
|
@@ -1037,7 +1038,7 @@ async function handleAllow(
|
|
|
1037
1038
|
);
|
|
1038
1039
|
}
|
|
1039
1040
|
} catch (error) {
|
|
1040
|
-
console.error('[MIDDLEWARE] RBAC error:', error);
|
|
1041
|
+
console.error('[MIDDLEWARE] RBAC error:', errForLog(error));
|
|
1041
1042
|
|
|
1042
1043
|
// In development, fail open
|
|
1043
1044
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errForLog } from '../lib/log-safe';
|
|
1
2
|
/**
|
|
2
3
|
* Page RBAC Check Module
|
|
3
4
|
*
|
|
@@ -262,7 +263,7 @@ export async function checkPagePermission(
|
|
|
262
263
|
};
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
console.error('[RBAC] Proxy error:', error);
|
|
266
|
+
console.error('[RBAC] Proxy error:', errForLog(error));
|
|
266
267
|
return {
|
|
267
268
|
allowed: false,
|
|
268
269
|
reason: 'rbac_service_unavailable',
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from '../../lib/app-slug';
|
|
28
28
|
import { siteEvents, getClientIp } from '../../lib/site-logger';
|
|
29
29
|
import { logExceptionWithCorrelation } from '../../lib/safe-error-response';
|
|
30
|
+
import { errForLog } from '../../lib/log-safe';
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* 4.8.9: answered (status 500) when a sign-out did not finish. 4.8.10 (BAPert 76297): TWO sentences, one per cause, each true for its
|
|
@@ -79,7 +80,13 @@ export async function POST(req: NextRequest) {
|
|
|
79
80
|
await revokeSessionAtIdp(req);
|
|
80
81
|
} catch (error) {
|
|
81
82
|
idpRevokeFailed = true;
|
|
82
|
-
|
|
83
|
+
// "STILL LIVE" only when the IdP showed it (a forced refresh succeeded); otherwise say what is known: it was not confirmed.
|
|
84
|
+
console.error(
|
|
85
|
+
(error as { grantLive?: boolean } | null)?.grantLive === true
|
|
86
|
+
? '[LOGOUT_ROUTE] IdP revoke failed - the IdP refresh token is STILL LIVE:'
|
|
87
|
+
: '[LOGOUT_ROUTE] IdP revoke could not be confirmed (the grant may already be dead):',
|
|
88
|
+
errForLog(error),
|
|
89
|
+
);
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
92
|
|
|
@@ -91,7 +98,7 @@ export async function POST(req: NextRequest) {
|
|
|
91
98
|
console.info('[LOGOUT_ROUTE] Session deleted from store');
|
|
92
99
|
} catch (error) {
|
|
93
100
|
localDeleteFailed = true;
|
|
94
|
-
console.error('[LOGOUT_ROUTE] Failed to delete session - the server session is STILL LIVE:', error);
|
|
101
|
+
console.error('[LOGOUT_ROUTE] Failed to delete session - the server session is STILL LIVE:', errForLog(error));
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
import { NextResponse } from 'next/server';
|
|
31
31
|
import { getIDPClientConfig } from '../../lib/idp-client-config';
|
|
32
32
|
import { secretSafeJson } from '../../lib/never-in-response';
|
|
33
|
+
import { errForLog } from '../../lib/log-safe';
|
|
33
34
|
|
|
34
35
|
export interface PublicAuthSettings {
|
|
35
36
|
// OAuth providers enabled for this client
|
|
@@ -95,7 +96,7 @@ export async function GET() {
|
|
|
95
96
|
config = await getIDPClientConfig();
|
|
96
97
|
} catch (error) {
|
|
97
98
|
// Keep the loud line - it is what finally unmasked this in production.
|
|
98
|
-
console.error('[AUTH_SETTINGS] Failed to get settings:', error);
|
|
99
|
+
console.error('[AUTH_SETTINGS] Failed to get settings:', errForLog(error));
|
|
99
100
|
// The `degraded: true` shape that used to live here (240447) is gone
|
|
100
101
|
// deliberately. It still answered `success: true` with a full invented
|
|
101
102
|
// policy and merely LABELLED the guess - which BAPert v32 rules out:
|
package/src/server/auth-guard.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { decodeSession } from './decode-session';
|
|
|
14
14
|
import { getIDPClientConfig } from '../lib/idp-client-config';
|
|
15
15
|
import { getSessionCookieName, getSecureSessionCookieName } from '../lib/app-slug';
|
|
16
16
|
import type { SessionData } from '../lib/session-store';
|
|
17
|
+
import { errForLog } from '../lib/log-safe';
|
|
17
18
|
|
|
18
19
|
// =============================================================================
|
|
19
20
|
// TYPES
|
|
@@ -89,7 +90,7 @@ export async function authGuard(options?: AuthGuardOptions): Promise<AuthGuardRe
|
|
|
89
90
|
decoded = await decodeSession();
|
|
90
91
|
} catch (error) {
|
|
91
92
|
// Redis unreachable or startup failure → fail closed
|
|
92
|
-
console.error('[AUTH-GUARD] Session decode failed (service error):',
|
|
93
|
+
console.error('[AUTH-GUARD] Session decode failed (service error):', errForLog(error));
|
|
93
94
|
redirect(serviceUnavailableUrl);
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -122,7 +123,7 @@ export async function authGuard(options?: AuthGuardOptions): Promise<AuthGuardRe
|
|
|
122
123
|
requires2FA = config.authSettings?.require2FA ?? true;
|
|
123
124
|
} catch (error) {
|
|
124
125
|
// If we can't check 2FA config, fail closed
|
|
125
|
-
console.error('[AUTH-GUARD] 2FA config check failed:',
|
|
126
|
+
console.error('[AUTH-GUARD] 2FA config check failed:', errForLog(error));
|
|
126
127
|
redirect(serviceUnavailableUrl);
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -186,7 +187,7 @@ export async function authGuard(options?: AuthGuardOptions): Promise<AuthGuardRe
|
|
|
186
187
|
if (error && typeof error === 'object' && 'digest' in error) {
|
|
187
188
|
throw error;
|
|
188
189
|
}
|
|
189
|
-
console.error(`[AUTH-GUARD] Custom check "${check.name}" error:`,
|
|
190
|
+
console.error(`[AUTH-GUARD] Custom check "${check.name}" error:`, errForLog(error));
|
|
190
191
|
redirect(serviceUnavailableUrl);
|
|
191
192
|
}
|
|
192
193
|
}
|
package/src/server/auth.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type SessionData,
|
|
15
15
|
} from '../lib/session-store';
|
|
16
16
|
import { tokenLogId } from '../lib/token-log-id';
|
|
17
|
+
import { errForLog } from '../lib/log-safe';
|
|
17
18
|
import { resolveVerifiedSessionTokenFromRequest } from './verified-session-token';
|
|
18
19
|
|
|
19
20
|
export type IdpTokenResult =
|
|
@@ -134,20 +135,14 @@ export async function getAuthInstance() {
|
|
|
134
135
|
* `{error:'NO_SESSION'}`, and getSession() swallowed every Redis error into a bare `catch {}`. These helpers name
|
|
135
136
|
* the origin and make a swallowed read audible. Hard rules: every helper is wrapped so it can NEVER throw or change
|
|
136
137
|
* a return value; nothing here ever logs a token, a cookie VALUE or a Redis value - only a tokenLogId() fingerprint,
|
|
137
|
-
* cookie NAMES, booleans, and an error
|
|
138
|
+
* cookie NAMES, booleans, and an error NAME with its closed code/status (errForLog; never the message).
|
|
138
139
|
* -------------------------------------------------------------------------------------------------------------- */
|
|
139
140
|
|
|
140
|
-
/**
|
|
141
|
-
|
|
142
|
-
const raw = v instanceof Error ? v.message : String(v ?? '');
|
|
143
|
-
return raw.replace(/[A-Za-z0-9_\-.+/=]{24,}/g, '[redacted]').slice(0, 80);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** `catch {}` sites on the session read path: still swallowed, now audible. */
|
|
141
|
+
/** `catch {}` sites on the session read path: still swallowed, now audible. The line names the error and its closed code/status only: the
|
|
142
|
+
* message is dropped (BAPert 76553: a redacted-and-truncated message still leaked host names, ports and quoted input). */
|
|
147
143
|
function logSessionReadSwallowed(path: 'primary' | 'A' | 'B', err: unknown): void {
|
|
148
144
|
try {
|
|
149
|
-
|
|
150
|
-
console.warn(`[server-auth] SESSION_READ_SWALLOWED path=${path} err=${name} msg=${scrubForLog(err)}`);
|
|
145
|
+
console.warn(`[server-auth] SESSION_READ_SWALLOWED path=${path} ${errForLog(err)}`);
|
|
151
146
|
} catch {
|
|
152
147
|
/* a diagnostic must never change the outcome */
|
|
153
148
|
}
|
|
@@ -15,6 +15,7 @@ import { ensureInitialized } from '../lib/startup-init';
|
|
|
15
15
|
import { extractSessionTokenFromCookieValue } from '../lib/session-cookie-shape';
|
|
16
16
|
import { resolveVerifiedSessionCookie } from './verified-session-token';
|
|
17
17
|
import { tokenLogId } from '../lib/token-log-id';
|
|
18
|
+
import { errForLog } from '../lib/log-safe';
|
|
18
19
|
|
|
19
20
|
export interface DecodedSession {
|
|
20
21
|
sessionData: SessionData;
|
|
@@ -197,7 +198,7 @@ async function tryBetterAuthSession(
|
|
|
197
198
|
|
|
198
199
|
return { sessionData, jwtPayload };
|
|
199
200
|
} catch (error) {
|
|
200
|
-
console.warn('[DECODE-SESSION] Better Auth session check failed:',
|
|
201
|
+
console.warn('[DECODE-SESSION] Better Auth session check failed:', errForLog(error));
|
|
201
202
|
return null;
|
|
202
203
|
}
|
|
203
204
|
}
|
|
@@ -303,7 +304,7 @@ export async function decodeSession(
|
|
|
303
304
|
jwtPayload: (payload ?? { sessionToken }) as DecodedSession['jwtPayload'],
|
|
304
305
|
};
|
|
305
306
|
} catch (error) {
|
|
306
|
-
console.error('[DECODE-SESSION] Error:',
|
|
307
|
+
console.error('[DECODE-SESSION] Error:', errForLog(error));
|
|
307
308
|
return null;
|
|
308
309
|
}
|
|
309
310
|
}
|
package/src/server/with-auth.ts
CHANGED
|
@@ -17,6 +17,7 @@ import 'server-only';
|
|
|
17
17
|
import { NextRequest, NextResponse } from 'next/server';
|
|
18
18
|
import { decodeSession } from './decode-session';
|
|
19
19
|
import type { SessionData } from '../lib/session-store';
|
|
20
|
+
import { errForLog } from '../lib/log-safe';
|
|
20
21
|
|
|
21
22
|
// =============================================================================
|
|
22
23
|
// TYPES
|
|
@@ -83,7 +84,7 @@ export function withAuth(
|
|
|
83
84
|
|
|
84
85
|
return handler(req, auth);
|
|
85
86
|
} catch (error) {
|
|
86
|
-
console.error('[WITH-AUTH] Error:',
|
|
87
|
+
console.error('[WITH-AUTH] Error:', errForLog(error));
|
|
87
88
|
return NextResponse.json(
|
|
88
89
|
{ error: 'Internal Server Error', message: 'Auth check failed' },
|
|
89
90
|
{ status: 500 }
|