@payez/next-mvp 3.9.0 → 4.0.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/dist/api/auth-handler.d.ts +1 -2
- package/dist/api/auth-handler.js +9 -9
- package/dist/api-handlers/account/change-password.js +110 -112
- package/dist/api-handlers/admin/analytics.d.ts +19 -20
- package/dist/api-handlers/admin/analytics.js +378 -379
- package/dist/api-handlers/admin/audit.d.ts +19 -20
- package/dist/api-handlers/admin/audit.js +213 -214
- package/dist/api-handlers/admin/index.d.ts +21 -22
- package/dist/api-handlers/admin/index.js +42 -43
- package/dist/api-handlers/admin/redis-sessions.d.ts +35 -36
- package/dist/api-handlers/admin/redis-sessions.js +203 -204
- package/dist/api-handlers/admin/sessions.d.ts +20 -21
- package/dist/api-handlers/admin/sessions.js +283 -284
- package/dist/api-handlers/admin/site-logs.d.ts +45 -46
- package/dist/api-handlers/admin/site-logs.js +317 -318
- package/dist/api-handlers/admin/stats.d.ts +20 -21
- package/dist/api-handlers/admin/stats.js +239 -240
- package/dist/api-handlers/admin/users.d.ts +19 -20
- package/dist/api-handlers/admin/users.js +221 -222
- package/dist/api-handlers/admin/vibe-data.d.ts +79 -80
- package/dist/api-handlers/admin/vibe-data.js +267 -268
- package/dist/api-handlers/auth/refresh.js +633 -635
- package/dist/api-handlers/auth/signout.js +186 -187
- package/dist/api-handlers/auth/status.js +4 -7
- package/dist/api-handlers/auth/update-session.d.ts +1 -1
- package/dist/api-handlers/auth/update-session.js +12 -14
- package/dist/api-handlers/auth/verify-code.d.ts +43 -43
- package/dist/api-handlers/auth/verify-code.js +90 -94
- package/dist/api-handlers/session/viability.js +114 -146
- package/dist/api-handlers/test/force-expire.js +59 -65
- package/dist/auth/auth-decision.js +182 -182
- package/dist/auth/better-auth.d.ts +3 -6
- package/dist/auth/better-auth.js +3 -6
- package/dist/auth/route-config.js +2 -2
- package/dist/auth/utils/token-utils.d.ts +83 -84
- package/dist/auth/utils/token-utils.js +218 -219
- package/dist/client/AuthContext.js +115 -112
- package/dist/client/better-auth-client.d.ts +1020 -961
- package/dist/client/better-auth-client.js +54 -7
- package/dist/client/fetch-with-auth.js +2 -2
- package/dist/components/SessionSync.js +121 -119
- package/dist/components/account/MobileNavDrawer.js +64 -64
- package/dist/components/account/UserAvatarMenu.js +91 -88
- package/dist/components/admin/VibeAdminLayout.js +71 -69
- package/dist/hooks/useAuth.js +9 -7
- package/dist/hooks/useAuthSettings.js +93 -93
- package/dist/hooks/useAvailableProviders.d.ts +43 -45
- package/dist/hooks/useAvailableProviders.js +112 -108
- package/dist/hooks/useSessionExpiration.d.ts +2 -3
- package/dist/hooks/useSessionExpiration.js +2 -2
- package/dist/hooks/useViabilitySession.js +3 -2
- package/dist/index.js +4 -6
- package/dist/lib/app-slug.d.ts +95 -95
- package/dist/lib/app-slug.js +172 -172
- package/dist/lib/standardized-client-api.js +10 -5
- package/dist/lib/startup-init.js +21 -25
- package/dist/lib/test-aware-get-token.js +86 -81
- package/dist/lib/token-lifecycle.d.ts +78 -52
- package/dist/lib/token-lifecycle.js +360 -398
- package/dist/pages/admin-login/page.js +73 -83
- package/dist/pages/client-admin/ClientSiteAdminPage.js +179 -177
- package/dist/pages/login/page.js +202 -211
- package/dist/pages/showcase/ShowcasePage.js +142 -140
- package/dist/pages/test-env/EmergencyLogoutPage.js +99 -98
- package/dist/pages/test-env/JwtInspectPage.js +116 -114
- package/dist/pages/test-env/RefreshTokenPage.js +4 -2
- package/dist/pages/test-env/TestEnvPage.js +51 -49
- package/dist/pages/verify-code/page.js +412 -408
- package/dist/routes/auth/logout.d.ts +31 -31
- package/dist/routes/auth/logout.js +98 -113
- package/dist/routes/auth/nextauth.d.ts +14 -11
- package/dist/routes/auth/nextauth.js +25 -57
- package/dist/routes/auth/session.js +157 -179
- package/dist/routes/auth/viability.js +190 -201
- package/dist/server/auth.d.ts +50 -0
- package/dist/server/auth.js +62 -0
- package/dist/stores/authStore.js +19 -23
- package/dist/utils/logout.js +5 -5
- package/package.json +1 -3
- package/src/api/auth-handler.ts +550 -549
- package/src/api-handlers/account/change-password.ts +5 -8
- package/src/api-handlers/admin/analytics.ts +4 -6
- package/src/api-handlers/admin/audit.ts +5 -7
- package/src/api-handlers/admin/index.ts +1 -2
- package/src/api-handlers/admin/redis-sessions.ts +6 -8
- package/src/api-handlers/admin/sessions.ts +5 -7
- package/src/api-handlers/admin/site-logs.ts +8 -10
- package/src/api-handlers/admin/stats.ts +4 -6
- package/src/api-handlers/admin/users.ts +5 -7
- package/src/api-handlers/admin/vibe-data.ts +10 -12
- package/src/api-handlers/auth/refresh.ts +5 -7
- package/src/api-handlers/auth/signout.ts +5 -6
- package/src/api-handlers/auth/status.ts +4 -7
- package/src/api-handlers/auth/update-session.ts +123 -125
- package/src/api-handlers/auth/verify-code.ts +9 -13
- package/src/api-handlers/session/viability.ts +10 -47
- package/src/api-handlers/test/force-expire.ts +4 -11
- package/src/auth/auth-decision.ts +1 -1
- package/src/auth/better-auth.ts +138 -141
- package/src/auth/route-config.ts +219 -219
- package/src/auth/utils/token-utils.ts +0 -1
- package/src/client/AuthContext.tsx +6 -2
- package/src/client/better-auth-client.ts +54 -7
- package/src/client/fetch-with-auth.ts +47 -47
- package/src/components/SessionSync.tsx +6 -5
- package/src/components/account/MobileNavDrawer.tsx +3 -3
- package/src/components/account/UserAvatarMenu.tsx +6 -3
- package/src/components/admin/VibeAdminLayout.tsx +4 -2
- package/src/config/logger.ts +1 -1
- package/src/hooks/useAuth.ts +117 -115
- package/src/hooks/useAuthSettings.ts +2 -2
- package/src/hooks/useAvailableProviders.ts +9 -5
- package/src/hooks/useSessionExpiration.ts +101 -102
- package/src/hooks/useViabilitySession.ts +336 -335
- package/src/index.ts +60 -63
- package/src/lib/api-handler.ts +0 -1
- package/src/lib/app-slug.ts +6 -6
- package/src/lib/standardized-client-api.ts +901 -895
- package/src/lib/startup-init.ts +243 -247
- package/src/lib/test-aware-get-token.ts +22 -12
- package/src/lib/token-lifecycle.ts +12 -53
- package/src/pages/admin-login/page.tsx +9 -17
- package/src/pages/client-admin/ClientSiteAdminPage.tsx +4 -2
- package/src/pages/login/page.tsx +21 -28
- package/src/pages/showcase/ShowcasePage.tsx +4 -2
- package/src/pages/test-env/EmergencyLogoutPage.tsx +7 -6
- package/src/pages/test-env/JwtInspectPage.tsx +5 -3
- package/src/pages/test-env/RefreshTokenPage.tsx +157 -155
- package/src/pages/test-env/TestEnvPage.tsx +4 -2
- package/src/pages/verify-code/page.tsx +10 -6
- package/src/routes/auth/logout.ts +7 -25
- package/src/routes/auth/nextauth.ts +45 -71
- package/src/routes/auth/session.ts +25 -50
- package/src/routes/auth/viability.ts +7 -19
- package/src/server/auth.ts +60 -0
- package/src/stores/authStore.ts +1899 -1904
- package/src/utils/logout.ts +30 -30
- package/src/auth/auth-options.ts +0 -237
- package/src/auth/callbacks/index.ts +0 -7
- package/src/auth/callbacks/jwt.ts +0 -382
- package/src/auth/callbacks/session.ts +0 -243
- package/src/auth/callbacks/signin.ts +0 -56
- package/src/auth/events/index.ts +0 -5
- package/src/auth/events/signout.ts +0 -33
- package/src/auth/providers/credentials.ts +0 -256
- package/src/auth/providers/index.ts +0 -6
- package/src/auth/providers/oauth.ts +0 -114
- package/src/lib/nextauth-secret.ts +0 -121
- package/src/types/next-auth.d.ts +0 -15
|
@@ -1,114 +1,116 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
'use client';
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.JwtInspectPage = JwtInspectPage;
|
|
5
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
// Decode JWT header (contains kid, alg, typ)
|
|
9
|
-
function decodeJwtHeader(token) {
|
|
10
|
-
try {
|
|
11
|
-
const parts = token.split('.');
|
|
12
|
-
if (parts.length !== 3)
|
|
13
|
-
return null;
|
|
14
|
-
const header = parts[0].replace(/-/g, '+').replace(/_/g, '/');
|
|
15
|
-
const decoded = atob(header);
|
|
16
|
-
return JSON.parse(decoded);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
// Decode JWT payload (contains claims)
|
|
23
|
-
function decodeJwtPayload(token) {
|
|
24
|
-
try {
|
|
25
|
-
const parts = token.split('.');
|
|
26
|
-
if (parts.length !== 3)
|
|
27
|
-
return null;
|
|
28
|
-
const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
29
|
-
const decoded = atob(payload);
|
|
30
|
-
return JSON.parse(decoded);
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Session Inspector Page
|
|
38
|
-
*
|
|
39
|
-
* Debug page for inspecting session data from Redis.
|
|
40
|
-
* Shows user info, roles, 2FA status, and tokens.
|
|
41
|
-
*
|
|
42
|
-
* Usage in consuming app:
|
|
43
|
-
* ```typescript
|
|
44
|
-
* // app/test-env/jwt-inspect/page.tsx
|
|
45
|
-
* export { JwtInspectPage as default } from '@payez/next-mvp/pages/test-env';
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
function JwtInspectPage() {
|
|
49
|
-
const { data:
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const [
|
|
53
|
-
const [
|
|
54
|
-
|
|
55
|
-
(0,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.JwtInspectPage = JwtInspectPage;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const better_auth_client_1 = require("../../client/better-auth-client");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
// Decode JWT header (contains kid, alg, typ)
|
|
9
|
+
function decodeJwtHeader(token) {
|
|
10
|
+
try {
|
|
11
|
+
const parts = token.split('.');
|
|
12
|
+
if (parts.length !== 3)
|
|
13
|
+
return null;
|
|
14
|
+
const header = parts[0].replace(/-/g, '+').replace(/_/g, '/');
|
|
15
|
+
const decoded = atob(header);
|
|
16
|
+
return JSON.parse(decoded);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Decode JWT payload (contains claims)
|
|
23
|
+
function decodeJwtPayload(token) {
|
|
24
|
+
try {
|
|
25
|
+
const parts = token.split('.');
|
|
26
|
+
if (parts.length !== 3)
|
|
27
|
+
return null;
|
|
28
|
+
const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
29
|
+
const decoded = atob(payload);
|
|
30
|
+
return JSON.parse(decoded);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Session Inspector Page
|
|
38
|
+
*
|
|
39
|
+
* Debug page for inspecting session data from Redis.
|
|
40
|
+
* Shows user info, roles, 2FA status, and tokens.
|
|
41
|
+
*
|
|
42
|
+
* Usage in consuming app:
|
|
43
|
+
* ```typescript
|
|
44
|
+
* // app/test-env/jwt-inspect/page.tsx
|
|
45
|
+
* export { JwtInspectPage as default } from '@payez/next-mvp/pages/test-env';
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
function JwtInspectPage() {
|
|
49
|
+
const { data: sessionData, isPending } = better_auth_client_1.authClient.useSession();
|
|
50
|
+
const session = sessionData;
|
|
51
|
+
const status = isPending ? 'loading' : session ? 'authenticated' : 'unauthenticated';
|
|
52
|
+
const [copied, setCopied] = (0, react_1.useState)(null);
|
|
53
|
+
const [isDarkMode, setIsDarkMode] = (0, react_1.useState)(false);
|
|
54
|
+
const [jwtHeader, setJwtHeader] = (0, react_1.useState)(null);
|
|
55
|
+
const [jwtPayload, setJwtPayload] = (0, react_1.useState)(null);
|
|
56
|
+
// Detect dark mode
|
|
57
|
+
(0, react_1.useEffect)(() => {
|
|
58
|
+
const checkDarkMode = () => {
|
|
59
|
+
const isDark = document.documentElement.classList.contains('dark') ||
|
|
60
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
61
|
+
setIsDarkMode(isDark);
|
|
62
|
+
};
|
|
63
|
+
checkDarkMode();
|
|
64
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
65
|
+
mediaQuery.addEventListener('change', checkDarkMode);
|
|
66
|
+
return () => mediaQuery.removeEventListener('change', checkDarkMode);
|
|
67
|
+
}, []);
|
|
68
|
+
// Decode JWT header and payload when accessToken changes
|
|
69
|
+
(0, react_1.useEffect)(() => {
|
|
70
|
+
const ext = session;
|
|
71
|
+
if (ext?.accessToken) {
|
|
72
|
+
setJwtHeader(decodeJwtHeader(ext.accessToken));
|
|
73
|
+
setJwtPayload(decodeJwtPayload(ext.accessToken));
|
|
74
|
+
}
|
|
75
|
+
}, [session]);
|
|
76
|
+
const copyToClipboard = (text, label) => {
|
|
77
|
+
navigator.clipboard.writeText(text);
|
|
78
|
+
setCopied(label);
|
|
79
|
+
setTimeout(() => setCopied(null), 2000);
|
|
80
|
+
};
|
|
81
|
+
if (status === 'loading') {
|
|
82
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen p-8 ${isDarkMode ? 'bg-slate-950 text-white' : 'bg-gray-50 text-gray-900'}`, children: "Loading session..." }));
|
|
83
|
+
}
|
|
84
|
+
if (status === 'unauthenticated') {
|
|
85
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen p-8 ${isDarkMode ? 'bg-slate-950 text-white' : 'bg-gray-50 text-gray-900'}`, children: (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-red-900/30 border border-red-800' : 'bg-red-50 border border-red-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-2", children: "Not Authenticated" }), (0, jsx_runtime_1.jsx)("p", { children: "Please log in to inspect session data." })] }) }));
|
|
86
|
+
}
|
|
87
|
+
// Extended session with all custom fields
|
|
88
|
+
const ext = session;
|
|
89
|
+
const user = ext?.user || {};
|
|
90
|
+
// Card styling helpers
|
|
91
|
+
const cardClass = isDarkMode ? 'bg-slate-900 border border-slate-700' : 'bg-white border border-gray-200';
|
|
92
|
+
const labelClass = isDarkMode ? 'text-slate-400' : 'text-gray-500';
|
|
93
|
+
const valueClass = isDarkMode ? 'text-white' : 'text-gray-900';
|
|
94
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen p-8 ${isDarkMode ? 'bg-slate-950 text-white' : 'bg-gray-50 text-gray-900'}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-4xl mx-auto space-y-6", children: [(0, jsx_runtime_1.jsx)("h1", { className: "text-2xl font-bold", children: "Session Inspector" }), (0, jsx_runtime_1.jsx)("p", { className: `text-sm ${labelClass}`, children: "Session data from Redis (via NextAuth session callback)" }), (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${cardClass}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "User Identity" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsx)(InfoRow, { label: "User ID", value: user.id, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Email", value: user.email, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Name", value: user.name, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "OAuth Provider", value: user.oauthProvider, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "IDP Client ID", value: user.idpClientId, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Merchant ID", value: user.merchantId, labelClass: labelClass, valueClass: valueClass })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-purple-900/30 border border-purple-700' : 'bg-purple-50 border border-purple-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "Roles" }), user.roles && user.roles.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2", children: user.roles.map((role) => ((0, jsx_runtime_1.jsx)("span", { className: `px-3 py-1 rounded-full text-sm font-medium ${isDarkMode ? 'bg-purple-800 text-purple-100' : 'bg-purple-200 text-purple-800'}`, children: role }, role))) })) : ((0, jsx_runtime_1.jsx)("p", { className: labelClass, children: "No roles assigned" }))] }), (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-yellow-900/30 border border-yellow-700' : 'bg-yellow-50 border border-yellow-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "2FA Status" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "2FA Verified:" }), ' ', (0, jsx_runtime_1.jsx)(StatusBadge, { value: user.twoFactorSessionVerified, trueText: "Yes", falseText: "No", isDarkMode: isDarkMode })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "Requires 2FA:" }), ' ', (0, jsx_runtime_1.jsx)(StatusBadge, { value: user.requiresTwoFactor, trueText: "Yes", falseText: "No", isDarkMode: isDarkMode, invertColors: true })] }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Auth Methods (AMR)", value: user.authenticationMethods?.join(', '), labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Auth Level (ACR)", value: user.authenticationLevel, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "MFA Completed At", value: user.mfaCompletedAt ? new Date(user.mfaCompletedAt).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "MFA Expires At", value: user.mfaExpiresAt ? new Date(user.mfaExpiresAt).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-blue-900/30 border border-blue-700' : 'bg-blue-50 border border-blue-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "Tokens" }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "Session Token (Redis Key):" }), ext.sessionToken && ((0, jsx_runtime_1.jsx)(CopyButton, { onClick: () => copyToClipboard(ext.sessionToken, 'session'), copied: copied === 'session', isDarkMode: isDarkMode }))] }), (0, jsx_runtime_1.jsx)("code", { className: `block p-2 rounded text-xs break-all ${isDarkMode ? 'bg-slate-800' : 'bg-gray-100'}`, children: ext.sessionToken || 'N/A' })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between mb-2", children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "Access Token (IDP):" }), ext.accessToken && ((0, jsx_runtime_1.jsx)(CopyButton, { onClick: () => copyToClipboard(ext.accessToken, 'access'), copied: copied === 'access', isDarkMode: isDarkMode }))] }), (0, jsx_runtime_1.jsx)("code", { className: `block p-2 rounded text-xs break-all max-h-24 overflow-auto ${isDarkMode ? 'bg-slate-800' : 'bg-gray-100'}`, children: ext.accessToken || 'N/A' })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "Has Refresh Token:" }), ' ', (0, jsx_runtime_1.jsx)(StatusBadge, { value: !!ext.refreshToken, trueText: "Yes", falseText: "No", isDarkMode: isDarkMode })] }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Access Token Expires", value: ext.accessTokenExpires ? new Date(ext.accessTokenExpires).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass })] })] })] }), jwtHeader && ((0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-orange-900/30 border border-orange-700' : 'bg-orange-50 border border-orange-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "JWT Header" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsx)(InfoRow, { label: "Algorithm (alg)", value: jwtHeader.alg, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Type (typ)", value: jwtHeader.typ, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: labelClass, children: "Key ID (kid):" }), ' ', (0, jsx_runtime_1.jsx)("span", { className: `font-mono ${jwtHeader.kid ? (isDarkMode ? 'text-green-400' : 'text-green-600') : (isDarkMode ? 'text-red-400' : 'text-red-600')}`, children: jwtHeader.kid || 'NOT PRESENT' })] }), Object.entries(jwtHeader)
|
|
95
|
+
.filter(([key]) => !['alg', 'typ', 'kid'].includes(key))
|
|
96
|
+
.map(([key, value]) => ((0, jsx_runtime_1.jsx)(InfoRow, { label: key, value: typeof value === 'object' ? JSON.stringify(value) : String(value), labelClass: labelClass, valueClass: valueClass }, key)))] })] })), jwtPayload && ((0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-green-900/30 border border-green-700' : 'bg-green-50 border border-green-200'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "JWT Payload Claims" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsx)(InfoRow, { label: "Subject (sub)", value: jwtPayload.sub, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Issuer (iss)", value: jwtPayload.iss, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Audience (aud)", value: Array.isArray(jwtPayload.aud) ? jwtPayload.aud.join(', ') : jwtPayload.aud, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Client ID", value: jwtPayload.client_id, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Expires (exp)", value: jwtPayload.exp ? new Date(jwtPayload.exp * 1000).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Issued At (iat)", value: jwtPayload.iat ? new Date(jwtPayload.iat * 1000).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "AMR (Auth Methods)", value: Array.isArray(jwtPayload.amr) ? jwtPayload.amr.join(', ') : jwtPayload.amr, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "ACR (Auth Context)", value: jwtPayload.acr, labelClass: labelClass, valueClass: valueClass })] })] })), (0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${cardClass}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "Session Metadata" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-sm", children: [(0, jsx_runtime_1.jsx)(InfoRow, { label: "Session Expires", value: session?.expires ? new Date(session.expires).toISOString() : undefined, labelClass: labelClass, valueClass: valueClass }), (0, jsx_runtime_1.jsx)(InfoRow, { label: "Error", value: ext.error, labelClass: labelClass, valueClass: ext.error ? 'text-red-500' : valueClass })] })] }), (0, jsx_runtime_1.jsxs)("details", { className: `p-4 rounded-lg ${cardClass}`, children: [(0, jsx_runtime_1.jsx)("summary", { className: "font-semibold cursor-pointer", children: "Raw Session Data (Click to expand)" }), (0, jsx_runtime_1.jsx)("pre", { className: `mt-4 text-xs overflow-auto p-3 rounded ${isDarkMode ? 'bg-slate-800' : 'bg-gray-100'}`, children: JSON.stringify(session, null, 2) })] })] }) }));
|
|
97
|
+
}
|
|
98
|
+
// Helper Components
|
|
99
|
+
function InfoRow({ label, value, labelClass, valueClass, }) {
|
|
100
|
+
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("span", { className: labelClass, children: [label, ":"] }), ' ', (0, jsx_runtime_1.jsx)("span", { className: valueClass, children: value || 'N/A' })] }));
|
|
101
|
+
}
|
|
102
|
+
function StatusBadge({ value, trueText, falseText, isDarkMode, invertColors = false, }) {
|
|
103
|
+
const isPositive = invertColors ? !value : value;
|
|
104
|
+
const colorClass = isPositive
|
|
105
|
+
? isDarkMode ? 'bg-green-800 text-green-100' : 'bg-green-200 text-green-800'
|
|
106
|
+
: isDarkMode ? 'bg-red-800 text-red-100' : 'bg-red-200 text-red-800';
|
|
107
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: `px-2 py-0.5 rounded text-xs font-medium ${colorClass}`, children: value ? trueText : falseText }));
|
|
108
|
+
}
|
|
109
|
+
function CopyButton({ onClick, copied, isDarkMode, }) {
|
|
110
|
+
return ((0, jsx_runtime_1.jsx)("button", { onClick: onClick, className: `px-2 py-1 rounded text-xs ${copied
|
|
111
|
+
? 'bg-green-600 text-white'
|
|
112
|
+
: isDarkMode
|
|
113
|
+
? 'bg-slate-700 hover:bg-slate-600 text-white'
|
|
114
|
+
: 'bg-gray-200 hover:bg-gray-300 text-gray-700'}`, children: copied ? 'Copied!' : 'Copy' }));
|
|
115
|
+
}
|
|
116
|
+
exports.default = JwtInspectPage;
|
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.RefreshTokenPage = RefreshTokenPage;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
const react_1 = require("react");
|
|
7
|
-
const
|
|
7
|
+
const better_auth_client_1 = require("../../client/better-auth-client");
|
|
8
8
|
/**
|
|
9
9
|
* Refresh Token Test Page
|
|
10
10
|
*
|
|
@@ -19,7 +19,9 @@ const react_2 = require("next-auth/react");
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
function RefreshTokenPage() {
|
|
22
|
-
const { data: session
|
|
22
|
+
const { data: session } = better_auth_client_1.authClient.useSession();
|
|
23
|
+
// TODO: Better Auth session refresh
|
|
24
|
+
const update = async () => { };
|
|
23
25
|
const [result, setResult] = (0, react_1.useState)(null);
|
|
24
26
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
25
27
|
const [sessionDetails, setSessionDetails] = (0, react_1.useState)(null);
|
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
'use client';
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.TestEnvPage = TestEnvPage;
|
|
8
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const link_1 = __importDefault(require("next/link"));
|
|
12
|
-
/**
|
|
13
|
-
* Test Environment Index Page
|
|
14
|
-
*
|
|
15
|
-
* Debug tools index showing session status and links to debug pages.
|
|
16
|
-
*
|
|
17
|
-
* Usage in consuming app:
|
|
18
|
-
* ```typescript
|
|
19
|
-
* // app/test-env/page.tsx
|
|
20
|
-
* export { TestEnvPage as default } from '@payez/next-mvp/pages/test-env';
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
function TestEnvPage() {
|
|
24
|
-
const { data:
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TestEnvPage = TestEnvPage;
|
|
8
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
9
|
+
const better_auth_client_1 = require("../../client/better-auth-client");
|
|
10
|
+
const react_1 = require("react");
|
|
11
|
+
const link_1 = __importDefault(require("next/link"));
|
|
12
|
+
/**
|
|
13
|
+
* Test Environment Index Page
|
|
14
|
+
*
|
|
15
|
+
* Debug tools index showing session status and links to debug pages.
|
|
16
|
+
*
|
|
17
|
+
* Usage in consuming app:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // app/test-env/page.tsx
|
|
20
|
+
* export { TestEnvPage as default } from '@payez/next-mvp/pages/test-env';
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function TestEnvPage() {
|
|
24
|
+
const { data: sessionData, isPending } = better_auth_client_1.authClient.useSession();
|
|
25
|
+
const session = sessionData;
|
|
26
|
+
const status = isPending ? 'loading' : session ? 'authenticated' : 'unauthenticated';
|
|
27
|
+
const [isDarkMode, setIsDarkMode] = (0, react_1.useState)(false);
|
|
28
|
+
(0, react_1.useEffect)(() => {
|
|
29
|
+
const checkDarkMode = () => {
|
|
30
|
+
const isDark = document.documentElement.classList.contains('dark') ||
|
|
31
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
32
|
+
setIsDarkMode(isDark);
|
|
33
|
+
};
|
|
34
|
+
checkDarkMode();
|
|
35
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
36
|
+
mediaQuery.addEventListener('change', checkDarkMode);
|
|
37
|
+
return () => mediaQuery.removeEventListener('change', checkDarkMode);
|
|
38
|
+
}, []);
|
|
39
|
+
const testPages = [
|
|
40
|
+
{
|
|
41
|
+
name: 'JWT Inspector',
|
|
42
|
+
url: '/test-env/jwt-inspect',
|
|
43
|
+
description: 'Decode and inspect JWT tokens, view all claims',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
const extSession = session;
|
|
47
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: `min-h-screen p-8 ${isDarkMode ? 'bg-slate-950 text-white' : 'bg-gray-50 text-gray-900'}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-4xl mx-auto", children: [(0, jsx_runtime_1.jsx)("h1", { className: "text-2xl font-bold mb-6", children: "Test Environment" }), (0, jsx_runtime_1.jsxs)("div", { className: `mb-8 p-4 rounded-lg ${isDarkMode ? 'bg-slate-900' : 'bg-white border'}`, children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-3", children: "Current Session" }), status === 'loading' ? ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500", children: "Loading..." })) : status === 'unauthenticated' ? ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-red-500", children: "Not logged in" })) : ((0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-2 text-sm", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "Email:" }) }), (0, jsx_runtime_1.jsx)("div", { children: session?.user?.email || 'N/A' }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "Has Access Token:" }) }), (0, jsx_runtime_1.jsx)("div", { className: extSession?.accessToken ? 'text-green-500' : 'text-red-500', children: extSession?.accessToken ? 'Yes' : 'No' }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "Has Refresh Token:" }) }), (0, jsx_runtime_1.jsx)("div", { className: extSession?.refreshToken ? 'text-green-500' : 'text-red-500', children: extSession?.refreshToken ? 'Yes' : 'No' }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "Token Expires:" }) }), (0, jsx_runtime_1.jsx)("div", { children: extSession?.accessTokenExpires ? new Date(extSession.accessTokenExpires).toLocaleString() : 'N/A' }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "2FA Required:" }) }), (0, jsx_runtime_1.jsx)("div", { children: extSession?.user?.requiresTwoFactor ? 'Yes' : 'No' }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("strong", { children: "2FA Verified:" }) }), (0, jsx_runtime_1.jsx)("div", { children: extSession?.user?.twoFactorSessionVerified ? 'Yes' : 'No' })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-8", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-lg font-semibold mb-4", children: "Debug Tools" }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: testPages.map((page) => ((0, jsx_runtime_1.jsxs)(link_1.default, { href: page.url, className: `p-4 rounded-lg transition-colors ${isDarkMode
|
|
48
|
+
? 'bg-slate-900 hover:bg-slate-800 border border-slate-700'
|
|
49
|
+
: 'bg-white hover:bg-gray-50 border'}`, children: [(0, jsx_runtime_1.jsx)("h3", { className: "font-semibold mb-2", children: page.name }), (0, jsx_runtime_1.jsx)("p", { className: `text-sm ${isDarkMode ? 'text-gray-400' : 'text-gray-600'}`, children: page.description })] }, page.url))) })] }), session && !extSession.refreshToken && ((0, jsx_runtime_1.jsxs)("div", { className: `p-4 rounded-lg ${isDarkMode ? 'bg-amber-900/30 border border-amber-700' : 'bg-amber-50 border border-amber-200'}`, children: [(0, jsx_runtime_1.jsx)("h3", { className: `font-semibold mb-2 ${isDarkMode ? 'text-amber-400' : 'text-amber-600'}`, children: "No Refresh Token" }), (0, jsx_runtime_1.jsx)("p", { className: `text-sm ${isDarkMode ? 'text-gray-300' : 'text-gray-600'}`, children: "This session does not have a refresh token. This typically means 2FA has not been completed. Token refresh will fail when the access token expires." })] }))] }) }));
|
|
50
|
+
}
|
|
51
|
+
exports.default = TestEnvPage;
|