@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.
Files changed (149) hide show
  1. package/dist/api/auth-handler.d.ts +1 -2
  2. package/dist/api/auth-handler.js +9 -9
  3. package/dist/api-handlers/account/change-password.js +110 -112
  4. package/dist/api-handlers/admin/analytics.d.ts +19 -20
  5. package/dist/api-handlers/admin/analytics.js +378 -379
  6. package/dist/api-handlers/admin/audit.d.ts +19 -20
  7. package/dist/api-handlers/admin/audit.js +213 -214
  8. package/dist/api-handlers/admin/index.d.ts +21 -22
  9. package/dist/api-handlers/admin/index.js +42 -43
  10. package/dist/api-handlers/admin/redis-sessions.d.ts +35 -36
  11. package/dist/api-handlers/admin/redis-sessions.js +203 -204
  12. package/dist/api-handlers/admin/sessions.d.ts +20 -21
  13. package/dist/api-handlers/admin/sessions.js +283 -284
  14. package/dist/api-handlers/admin/site-logs.d.ts +45 -46
  15. package/dist/api-handlers/admin/site-logs.js +317 -318
  16. package/dist/api-handlers/admin/stats.d.ts +20 -21
  17. package/dist/api-handlers/admin/stats.js +239 -240
  18. package/dist/api-handlers/admin/users.d.ts +19 -20
  19. package/dist/api-handlers/admin/users.js +221 -222
  20. package/dist/api-handlers/admin/vibe-data.d.ts +79 -80
  21. package/dist/api-handlers/admin/vibe-data.js +267 -268
  22. package/dist/api-handlers/auth/refresh.js +633 -635
  23. package/dist/api-handlers/auth/signout.js +186 -187
  24. package/dist/api-handlers/auth/status.js +4 -7
  25. package/dist/api-handlers/auth/update-session.d.ts +1 -1
  26. package/dist/api-handlers/auth/update-session.js +12 -14
  27. package/dist/api-handlers/auth/verify-code.d.ts +43 -43
  28. package/dist/api-handlers/auth/verify-code.js +90 -94
  29. package/dist/api-handlers/session/viability.js +114 -146
  30. package/dist/api-handlers/test/force-expire.js +59 -65
  31. package/dist/auth/auth-decision.js +182 -182
  32. package/dist/auth/better-auth.d.ts +3 -6
  33. package/dist/auth/better-auth.js +3 -6
  34. package/dist/auth/route-config.js +2 -2
  35. package/dist/auth/utils/token-utils.d.ts +83 -84
  36. package/dist/auth/utils/token-utils.js +218 -219
  37. package/dist/client/AuthContext.js +115 -112
  38. package/dist/client/better-auth-client.d.ts +1020 -961
  39. package/dist/client/better-auth-client.js +54 -7
  40. package/dist/client/fetch-with-auth.js +2 -2
  41. package/dist/components/SessionSync.js +121 -119
  42. package/dist/components/account/MobileNavDrawer.js +64 -64
  43. package/dist/components/account/UserAvatarMenu.js +91 -88
  44. package/dist/components/admin/VibeAdminLayout.js +71 -69
  45. package/dist/hooks/useAuth.js +9 -7
  46. package/dist/hooks/useAuthSettings.js +93 -93
  47. package/dist/hooks/useAvailableProviders.d.ts +43 -45
  48. package/dist/hooks/useAvailableProviders.js +112 -108
  49. package/dist/hooks/useSessionExpiration.d.ts +2 -3
  50. package/dist/hooks/useSessionExpiration.js +2 -2
  51. package/dist/hooks/useViabilitySession.js +3 -2
  52. package/dist/index.js +4 -6
  53. package/dist/lib/app-slug.d.ts +95 -95
  54. package/dist/lib/app-slug.js +172 -172
  55. package/dist/lib/standardized-client-api.js +10 -5
  56. package/dist/lib/startup-init.js +21 -25
  57. package/dist/lib/test-aware-get-token.js +86 -81
  58. package/dist/lib/token-lifecycle.d.ts +78 -52
  59. package/dist/lib/token-lifecycle.js +360 -398
  60. package/dist/pages/admin-login/page.js +73 -83
  61. package/dist/pages/client-admin/ClientSiteAdminPage.js +179 -177
  62. package/dist/pages/login/page.js +202 -211
  63. package/dist/pages/showcase/ShowcasePage.js +142 -140
  64. package/dist/pages/test-env/EmergencyLogoutPage.js +99 -98
  65. package/dist/pages/test-env/JwtInspectPage.js +116 -114
  66. package/dist/pages/test-env/RefreshTokenPage.js +4 -2
  67. package/dist/pages/test-env/TestEnvPage.js +51 -49
  68. package/dist/pages/verify-code/page.js +412 -408
  69. package/dist/routes/auth/logout.d.ts +31 -31
  70. package/dist/routes/auth/logout.js +98 -113
  71. package/dist/routes/auth/nextauth.d.ts +14 -11
  72. package/dist/routes/auth/nextauth.js +25 -57
  73. package/dist/routes/auth/session.js +157 -179
  74. package/dist/routes/auth/viability.js +190 -201
  75. package/dist/server/auth.d.ts +50 -0
  76. package/dist/server/auth.js +62 -0
  77. package/dist/stores/authStore.js +19 -23
  78. package/dist/utils/logout.js +5 -5
  79. package/package.json +1 -3
  80. package/src/api/auth-handler.ts +550 -549
  81. package/src/api-handlers/account/change-password.ts +5 -8
  82. package/src/api-handlers/admin/analytics.ts +4 -6
  83. package/src/api-handlers/admin/audit.ts +5 -7
  84. package/src/api-handlers/admin/index.ts +1 -2
  85. package/src/api-handlers/admin/redis-sessions.ts +6 -8
  86. package/src/api-handlers/admin/sessions.ts +5 -7
  87. package/src/api-handlers/admin/site-logs.ts +8 -10
  88. package/src/api-handlers/admin/stats.ts +4 -6
  89. package/src/api-handlers/admin/users.ts +5 -7
  90. package/src/api-handlers/admin/vibe-data.ts +10 -12
  91. package/src/api-handlers/auth/refresh.ts +5 -7
  92. package/src/api-handlers/auth/signout.ts +5 -6
  93. package/src/api-handlers/auth/status.ts +4 -7
  94. package/src/api-handlers/auth/update-session.ts +123 -125
  95. package/src/api-handlers/auth/verify-code.ts +9 -13
  96. package/src/api-handlers/session/viability.ts +10 -47
  97. package/src/api-handlers/test/force-expire.ts +4 -11
  98. package/src/auth/auth-decision.ts +1 -1
  99. package/src/auth/better-auth.ts +138 -141
  100. package/src/auth/route-config.ts +219 -219
  101. package/src/auth/utils/token-utils.ts +0 -1
  102. package/src/client/AuthContext.tsx +6 -2
  103. package/src/client/better-auth-client.ts +54 -7
  104. package/src/client/fetch-with-auth.ts +47 -47
  105. package/src/components/SessionSync.tsx +6 -5
  106. package/src/components/account/MobileNavDrawer.tsx +3 -3
  107. package/src/components/account/UserAvatarMenu.tsx +6 -3
  108. package/src/components/admin/VibeAdminLayout.tsx +4 -2
  109. package/src/config/logger.ts +1 -1
  110. package/src/hooks/useAuth.ts +117 -115
  111. package/src/hooks/useAuthSettings.ts +2 -2
  112. package/src/hooks/useAvailableProviders.ts +9 -5
  113. package/src/hooks/useSessionExpiration.ts +101 -102
  114. package/src/hooks/useViabilitySession.ts +336 -335
  115. package/src/index.ts +60 -63
  116. package/src/lib/api-handler.ts +0 -1
  117. package/src/lib/app-slug.ts +6 -6
  118. package/src/lib/standardized-client-api.ts +901 -895
  119. package/src/lib/startup-init.ts +243 -247
  120. package/src/lib/test-aware-get-token.ts +22 -12
  121. package/src/lib/token-lifecycle.ts +12 -53
  122. package/src/pages/admin-login/page.tsx +9 -17
  123. package/src/pages/client-admin/ClientSiteAdminPage.tsx +4 -2
  124. package/src/pages/login/page.tsx +21 -28
  125. package/src/pages/showcase/ShowcasePage.tsx +4 -2
  126. package/src/pages/test-env/EmergencyLogoutPage.tsx +7 -6
  127. package/src/pages/test-env/JwtInspectPage.tsx +5 -3
  128. package/src/pages/test-env/RefreshTokenPage.tsx +157 -155
  129. package/src/pages/test-env/TestEnvPage.tsx +4 -2
  130. package/src/pages/verify-code/page.tsx +10 -6
  131. package/src/routes/auth/logout.ts +7 -25
  132. package/src/routes/auth/nextauth.ts +45 -71
  133. package/src/routes/auth/session.ts +25 -50
  134. package/src/routes/auth/viability.ts +7 -19
  135. package/src/server/auth.ts +60 -0
  136. package/src/stores/authStore.ts +1899 -1904
  137. package/src/utils/logout.ts +30 -30
  138. package/src/auth/auth-options.ts +0 -237
  139. package/src/auth/callbacks/index.ts +0 -7
  140. package/src/auth/callbacks/jwt.ts +0 -382
  141. package/src/auth/callbacks/session.ts +0 -243
  142. package/src/auth/callbacks/signin.ts +0 -56
  143. package/src/auth/events/index.ts +0 -5
  144. package/src/auth/events/signout.ts +0 -33
  145. package/src/auth/providers/credentials.ts +0 -256
  146. package/src/auth/providers/index.ts +0 -6
  147. package/src/auth/providers/oauth.ts +0 -114
  148. package/src/lib/nextauth-secret.ts +0 -121
  149. package/src/types/next-auth.d.ts +0 -15
@@ -1,187 +1,186 @@
1
- "use strict";
2
- /**
3
- * Authentication Signout API Handler
4
- *
5
- * Handles user session termination and cookie cleanup.
6
- * This handler is designed to be imported and used by Next.js applications
7
- * using the @payez/next-mvp package.
8
- *
9
- * @version 2.0
10
- * @requires No authentication (public endpoint)
11
- */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.POST = void 0;
14
- exports.createSignoutHandler = createSignoutHandler;
15
- const server_1 = require("next/server");
16
- const headers_1 = require("next/headers");
17
- const session_store_1 = require("../../lib/session-store");
18
- const jwt_1 = require("next-auth/jwt");
19
- const app_slug_1 = require("../../lib/app-slug");
20
- // JWT decode helper - simple base64 decode without verification
21
- function jwtDecode(token) {
22
- try {
23
- const parts = token.split('.');
24
- if (parts.length !== 3)
25
- return null;
26
- const payload = parts[1];
27
- const decoded = Buffer.from(payload, 'base64').toString('utf-8');
28
- return JSON.parse(decoded);
29
- }
30
- catch (e) {
31
- return null;
32
- }
33
- }
34
- // Add protection headers to all responses
35
- function addSecurityHeaders(response) {
36
- response.headers.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';");
37
- response.headers.set('X-Frame-Options', 'DENY');
38
- response.headers.set('X-Content-Type-Options', 'nosniff');
39
- response.headers.set('X-XSS-Protection', '1; mode=block');
40
- response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
41
- response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
42
- response.headers.set('Permissions-Policy', 'geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()');
43
- response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
44
- response.headers.set('Pragma', 'no-cache');
45
- response.headers.set('Expires', '0');
46
- return response;
47
- }
48
- /**
49
- * Creates a signout handler for Next.js API routes
50
- *
51
- * @param config Configuration for NextAuth
52
- * @returns Next.js POST handler function
53
- *
54
- * @example
55
- * ```typescript
56
- * // In your app's /app/api/auth/signout/route.ts
57
- * import { createSignoutHandler } from '@payez/next-mvp/api-handlers/auth/signout';
58
- *
59
- * export const POST = createSignoutHandler({
60
- * nextAuthSecret: process.env.NEXTAUTH_SECRET!
61
- * });
62
- * ```
63
- */
64
- function createSignoutHandler(config) {
65
- const { nextAuthSecret } = config;
66
- return async function POST(req) {
67
- const cookieStore = await (0, headers_1.cookies)();
68
- // Get app-slug prefixed cookie names
69
- const sessionCookieName = (0, app_slug_1.getSessionCookieName)();
70
- const secureSessionCookieName = (0, app_slug_1.getSecureSessionCookieName)();
71
- // Handle chunked session tokens (for large JWTs)
72
- let sessionToken;
73
- const sessionTokenCookie = cookieStore.get(sessionCookieName);
74
- if (sessionTokenCookie?.value) {
75
- // Single cookie case
76
- sessionToken = sessionTokenCookie.value;
77
- }
78
- else {
79
- // Chunked cookie case - reconstruct from parts
80
- const chunkCookies = cookieStore.getAll()
81
- .filter(cookie => cookie.name.startsWith(`${sessionCookieName}.`))
82
- .sort((a, b) => {
83
- const aIndex = parseInt(a.name.split('.').pop() || '0');
84
- const bIndex = parseInt(b.name.split('.').pop() || '0');
85
- return aIndex - bIndex;
86
- });
87
- if (chunkCookies.length > 0) {
88
- sessionToken = chunkCookies.map(cookie => cookie.value).join('');
89
- }
90
- }
91
- // Get chunk cookies for cleanup count
92
- const chunkCookies = cookieStore.getAll()
93
- .filter(cookie => cookie.name.startsWith(`${sessionCookieName}.`));
94
- // Decode NextAuth JWT to extract the Redis session UUID before deletion
95
- let redisSessionToken = null;
96
- // First attempt: NextAuth getToken (verified + robust in most cases)
97
- // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
98
- try {
99
- const token = await (0, jwt_1.getToken)({ req, secret: nextAuthSecret, cookieName: (0, app_slug_1.getJwtCookieName)() });
100
- redisSessionToken = token?.sessionToken || token?.redisSessionId || null;
101
- }
102
- catch (e) {
103
- console.warn('[SIGNOUT] getToken() failed to extract session token (will try manual decode)');
104
- }
105
- // Second attempt: manual decode of the session cookie JWT (no verification)
106
- if (!redisSessionToken && (sessionToken || cookieStore.getAll().some(c => c.name.startsWith(`${sessionCookieName}.`)))) {
107
- try {
108
- // Reconstruct raw JWT from chunked cookies if necessary
109
- let rawJwt = null;
110
- const direct = cookieStore.get(sessionCookieName);
111
- if (direct?.value) {
112
- rawJwt = direct.value;
113
- }
114
- else {
115
- const chunks = cookieStore.getAll()
116
- .filter(c => c.name.startsWith(`${sessionCookieName}.`))
117
- .sort((a, b) => {
118
- const ai = parseInt(a.name.split('.').pop() || '0');
119
- const bi = parseInt(b.name.split('.').pop() || '0');
120
- return ai - bi;
121
- })
122
- .map(c => c.value);
123
- if (chunks.length > 0)
124
- rawJwt = chunks.join('');
125
- }
126
- if (rawJwt) {
127
- const decoded = jwtDecode(rawJwt);
128
- if (decoded && typeof decoded === 'object' && typeof decoded.sessionToken === 'string') {
129
- redisSessionToken = decoded.sessionToken;
130
- }
131
- }
132
- }
133
- catch (e) {
134
- console.warn('[SIGNOUT] Manual JWT decode failed to extract session token');
135
- }
136
- }
137
- // Delete Redis session if UUID was extracted
138
- if (redisSessionToken) {
139
- try {
140
- await (0, session_store_1.deleteSession)(redisSessionToken);
141
- console.info('[SIGNOUT] Redis session cleanup successful', {
142
- sessionToken: redisSessionToken.substring(0, 8) + '...'
143
- });
144
- }
145
- catch (sessionError) {
146
- // Log error but don't fail the signout process
147
- console.error('[SIGNOUT] Redis session cleanup failed', { error: sessionError });
148
- }
149
- }
150
- else {
151
- console.warn('[SIGNOUT] No Redis session token (UUID) extracted from cookie; skipping Redis deletion');
152
- }
153
- // Build response
154
- const responseData = {
155
- success: true,
156
- message: sessionToken ? 'Session deleted successfully' : 'No active session found',
157
- sessionDeleted: !!sessionToken,
158
- chunkCookiesDeleted: chunkCookies.length
159
- };
160
- const response = server_1.NextResponse.json(responseData);
161
- // Always clear cookies, regardless of success/failure (using app-slug prefixed names)
162
- try {
163
- response.cookies.delete(sessionCookieName);
164
- response.cookies.delete(secureSessionCookieName);
165
- response.cookies.delete((0, app_slug_1.getCsrfCookieName)());
166
- response.cookies.delete((0, app_slug_1.getSecureCsrfCookieName)());
167
- response.cookies.delete((0, app_slug_1.getCallbackUrlCookieName)());
168
- response.cookies.delete(`__Secure-${(0, app_slug_1.getCallbackUrlCookieName)()}`);
169
- response.cookies.delete('twoFactorSessionVerified');
170
- // Delete chunked session cookies
171
- chunkCookies.forEach(cookie => {
172
- response.cookies.delete(cookie.name);
173
- });
174
- }
175
- catch (cookieError) {
176
- console.error('[SIGNOUT] Cookie cleanup failed:', cookieError);
177
- }
178
- return addSecurityHeaders(response);
179
- };
180
- }
181
- /**
182
- * Default export for backward compatibility
183
- * Requires environment variable: NEXTAUTH_SECRET
184
- */
185
- exports.POST = createSignoutHandler({
186
- nextAuthSecret: process.env.NEXTAUTH_SECRET || ''
187
- });
1
+ "use strict";
2
+ /**
3
+ * Authentication Signout API Handler
4
+ *
5
+ * Handles user session termination and cookie cleanup.
6
+ * This handler is designed to be imported and used by Next.js applications
7
+ * using the @payez/next-mvp package.
8
+ *
9
+ * @version 2.0
10
+ * @requires No authentication (public endpoint)
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.POST = void 0;
14
+ exports.createSignoutHandler = createSignoutHandler;
15
+ const server_1 = require("next/server");
16
+ const headers_1 = require("next/headers");
17
+ const session_store_1 = require("../../lib/session-store");
18
+ const auth_1 = require("../../server/auth");
19
+ const app_slug_1 = require("../../lib/app-slug");
20
+ // JWT decode helper - simple base64 decode without verification
21
+ function jwtDecode(token) {
22
+ try {
23
+ const parts = token.split('.');
24
+ if (parts.length !== 3)
25
+ return null;
26
+ const payload = parts[1];
27
+ const decoded = Buffer.from(payload, 'base64').toString('utf-8');
28
+ return JSON.parse(decoded);
29
+ }
30
+ catch (e) {
31
+ return null;
32
+ }
33
+ }
34
+ // Add protection headers to all responses
35
+ function addSecurityHeaders(response) {
36
+ response.headers.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';");
37
+ response.headers.set('X-Frame-Options', 'DENY');
38
+ response.headers.set('X-Content-Type-Options', 'nosniff');
39
+ response.headers.set('X-XSS-Protection', '1; mode=block');
40
+ response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
41
+ response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
42
+ response.headers.set('Permissions-Policy', 'geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()');
43
+ response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
44
+ response.headers.set('Pragma', 'no-cache');
45
+ response.headers.set('Expires', '0');
46
+ return response;
47
+ }
48
+ /**
49
+ * Creates a signout handler for Next.js API routes
50
+ *
51
+ * @param config Configuration for NextAuth
52
+ * @returns Next.js POST handler function
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // In your app's /app/api/auth/signout/route.ts
57
+ * import { createSignoutHandler } from '@payez/next-mvp/api-handlers/auth/signout';
58
+ *
59
+ * export const POST = createSignoutHandler({
60
+ * nextAuthSecret: process.env.NEXTAUTH_SECRET!
61
+ * });
62
+ * ```
63
+ */
64
+ function createSignoutHandler(config) {
65
+ const { nextAuthSecret } = config;
66
+ return async function POST(req) {
67
+ const cookieStore = await (0, headers_1.cookies)();
68
+ // Get app-slug prefixed cookie names
69
+ const sessionCookieName = (0, app_slug_1.getSessionCookieName)();
70
+ const secureSessionCookieName = (0, app_slug_1.getSecureSessionCookieName)();
71
+ // Handle chunked session tokens (for large JWTs)
72
+ let sessionToken;
73
+ const sessionTokenCookie = cookieStore.get(sessionCookieName);
74
+ if (sessionTokenCookie?.value) {
75
+ // Single cookie case
76
+ sessionToken = sessionTokenCookie.value;
77
+ }
78
+ else {
79
+ // Chunked cookie case - reconstruct from parts
80
+ const chunkCookies = cookieStore.getAll()
81
+ .filter(cookie => cookie.name.startsWith(`${sessionCookieName}.`))
82
+ .sort((a, b) => {
83
+ const aIndex = parseInt(a.name.split('.').pop() || '0');
84
+ const bIndex = parseInt(b.name.split('.').pop() || '0');
85
+ return aIndex - bIndex;
86
+ });
87
+ if (chunkCookies.length > 0) {
88
+ sessionToken = chunkCookies.map(cookie => cookie.value).join('');
89
+ }
90
+ }
91
+ // Get chunk cookies for cleanup count
92
+ const chunkCookies = cookieStore.getAll()
93
+ .filter(cookie => cookie.name.startsWith(`${sessionCookieName}.`));
94
+ // Decode NextAuth JWT to extract the Redis session UUID before deletion
95
+ let redisSessionToken = null;
96
+ // First attempt: Better Auth getSession
97
+ try {
98
+ const betterAuthSession = await (0, auth_1.getSession)(req);
99
+ redisSessionToken = betterAuthSession?.session?.token || null;
100
+ }
101
+ catch (e) {
102
+ console.warn('[SIGNOUT] getSession() failed to extract session token (will try manual decode)');
103
+ }
104
+ // Second attempt: manual decode of the session cookie JWT (no verification)
105
+ if (!redisSessionToken && (sessionToken || cookieStore.getAll().some(c => c.name.startsWith(`${sessionCookieName}.`)))) {
106
+ try {
107
+ // Reconstruct raw JWT from chunked cookies if necessary
108
+ let rawJwt = null;
109
+ const direct = cookieStore.get(sessionCookieName);
110
+ if (direct?.value) {
111
+ rawJwt = direct.value;
112
+ }
113
+ else {
114
+ const chunks = cookieStore.getAll()
115
+ .filter(c => c.name.startsWith(`${sessionCookieName}.`))
116
+ .sort((a, b) => {
117
+ const ai = parseInt(a.name.split('.').pop() || '0');
118
+ const bi = parseInt(b.name.split('.').pop() || '0');
119
+ return ai - bi;
120
+ })
121
+ .map(c => c.value);
122
+ if (chunks.length > 0)
123
+ rawJwt = chunks.join('');
124
+ }
125
+ if (rawJwt) {
126
+ const decoded = jwtDecode(rawJwt);
127
+ if (decoded && typeof decoded === 'object' && typeof decoded.sessionToken === 'string') {
128
+ redisSessionToken = decoded.sessionToken;
129
+ }
130
+ }
131
+ }
132
+ catch (e) {
133
+ console.warn('[SIGNOUT] Manual JWT decode failed to extract session token');
134
+ }
135
+ }
136
+ // Delete Redis session if UUID was extracted
137
+ if (redisSessionToken) {
138
+ try {
139
+ await (0, session_store_1.deleteSession)(redisSessionToken);
140
+ console.info('[SIGNOUT] Redis session cleanup successful', {
141
+ sessionToken: redisSessionToken.substring(0, 8) + '...'
142
+ });
143
+ }
144
+ catch (sessionError) {
145
+ // Log error but don't fail the signout process
146
+ console.error('[SIGNOUT] Redis session cleanup failed', { error: sessionError });
147
+ }
148
+ }
149
+ else {
150
+ console.warn('[SIGNOUT] No Redis session token (UUID) extracted from cookie; skipping Redis deletion');
151
+ }
152
+ // Build response
153
+ const responseData = {
154
+ success: true,
155
+ message: sessionToken ? 'Session deleted successfully' : 'No active session found',
156
+ sessionDeleted: !!sessionToken,
157
+ chunkCookiesDeleted: chunkCookies.length
158
+ };
159
+ const response = server_1.NextResponse.json(responseData);
160
+ // Always clear cookies, regardless of success/failure (using app-slug prefixed names)
161
+ try {
162
+ response.cookies.delete(sessionCookieName);
163
+ response.cookies.delete(secureSessionCookieName);
164
+ response.cookies.delete((0, app_slug_1.getCsrfCookieName)());
165
+ response.cookies.delete((0, app_slug_1.getSecureCsrfCookieName)());
166
+ response.cookies.delete((0, app_slug_1.getCallbackUrlCookieName)());
167
+ response.cookies.delete(`__Secure-${(0, app_slug_1.getCallbackUrlCookieName)()}`);
168
+ response.cookies.delete('twoFactorSessionVerified');
169
+ // Delete chunked session cookies
170
+ chunkCookies.forEach(cookie => {
171
+ response.cookies.delete(cookie.name);
172
+ });
173
+ }
174
+ catch (cookieError) {
175
+ console.error('[SIGNOUT] Cookie cleanup failed:', cookieError);
176
+ }
177
+ return addSecurityHeaders(response);
178
+ };
179
+ }
180
+ /**
181
+ * Default export for backward compatibility
182
+ * Requires environment variable: NEXTAUTH_SECRET
183
+ */
184
+ exports.POST = createSignoutHandler({
185
+ nextAuthSecret: process.env.NEXTAUTH_SECRET || ''
186
+ });
@@ -2,15 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GET = GET;
4
4
  const server_1 = require("next/server");
5
- const jwt_1 = require("next-auth/jwt");
6
- const nextauth_secret_1 = require("../../lib/nextauth-secret");
5
+ const auth_1 = require("../../server/auth");
7
6
  const session_store_1 = require("../../lib/session-store");
8
- const app_slug_1 = require("../../lib/app-slug");
9
7
  async function GET(req) {
10
8
  try {
11
- let token = await (0, jwt_1.getToken)({ req, secret: await (0, nextauth_secret_1.resolveNextAuthSecret)(), cookieName: (0, app_slug_1.getJwtCookieName)() });
12
- // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
13
- const sessionToken = token?.sessionToken || token?.redisSessionId;
9
+ const betterAuthSession = await (0, auth_1.getSession)(req);
10
+ const sessionToken = betterAuthSession?.session?.token;
14
11
  if (!sessionToken) {
15
12
  return server_1.NextResponse.json({ success: false, error: 'No session token' }, { status: 401 });
16
13
  }
@@ -18,7 +15,7 @@ async function GET(req) {
18
15
  if (!sessionModel) {
19
16
  return server_1.NextResponse.json({ success: false, error: 'Session missing in Redis' }, { status: 401 });
20
17
  }
21
- return server_1.NextResponse.json({ success: true, userId: sessionModel.userId || null });
18
+ return server_1.NextResponse.json({ success: true, userId: betterAuthSession?.user?.id || sessionModel.userId || null });
22
19
  }
23
20
  catch (err) {
24
21
  return server_1.NextResponse.json({ success: false, error: err instanceof Error ? err.message : 'Unknown error' }, { status: 500 });
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { NextRequest, NextResponse } from 'next/server';
12
12
  interface UpdateSessionConfig {
13
- nextAuthSecret: string;
13
+ nextAuthSecret?: string;
14
14
  }
15
15
  /**
16
16
  * Creates an update-session handler for Next.js API routes
@@ -13,8 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.POST = void 0;
14
14
  exports.createUpdateSessionHandler = createUpdateSessionHandler;
15
15
  const server_1 = require("next/server");
16
- const jwt_1 = require("next-auth/jwt");
17
- const app_slug_1 = require("../../lib/app-slug");
16
+ const auth_1 = require("../../server/auth");
18
17
  // Add protection headers to all responses
19
18
  function addSecurityHeaders(response) {
20
19
  response.headers.set('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';");
@@ -57,26 +56,25 @@ function createUpdateSessionHandler(config) {
57
56
  return addSecurityHeaders(server_1.NextResponse.json({ error: 'Invalid JSON format' }, { status: 400 }));
58
57
  }
59
58
  const { twoFactorSessionVerified, twoFactorMethod } = body;
60
- // Get the current token
61
- const token = await (0, jwt_1.getToken)({ req, secret: nextAuthSecret, cookieName: (0, app_slug_1.getJwtCookieName)() });
62
- if (!token) {
59
+ // Get the current session from Better Auth
60
+ const session = await (0, auth_1.getSession)(req);
61
+ if (!session) {
63
62
  return addSecurityHeaders(server_1.NextResponse.json({ error: 'No session token available' }, { status: 401 }));
64
63
  }
65
- // Update the token with 2FA challenge completion status
66
- const updatedToken = {
67
- ...token,
64
+ // Update the session with 2FA challenge completion status
65
+ const updatedSession = {
68
66
  twoFactorSessionVerified: !!twoFactorSessionVerified,
69
- twoFactorMethod: twoFactorMethod || token.twoFactorMethod
67
+ twoFactorMethod: twoFactorMethod || session.twoFactorMethod
70
68
  };
71
69
  console.info('[UPDATE-SESSION] Session updated successfully', {
72
- userId: token.sub,
73
- twoFactorSessionVerified: updatedToken.twoFactorSessionVerified,
74
- twoFactorMethod: updatedToken.twoFactorMethod
70
+ userId: session.user?.id,
71
+ twoFactorSessionVerified: updatedSession.twoFactorSessionVerified,
72
+ twoFactorMethod: updatedSession.twoFactorMethod
75
73
  });
76
74
  const responseData = {
77
75
  success: true,
78
- twoFactorSessionVerified: updatedToken.twoFactorSessionVerified,
79
- twoFactorMethod: updatedToken.twoFactorMethod
76
+ twoFactorSessionVerified: updatedSession.twoFactorSessionVerified,
77
+ twoFactorMethod: updatedSession.twoFactorMethod
80
78
  };
81
79
  return addSecurityHeaders(server_1.NextResponse.json(responseData));
82
80
  }
@@ -1,43 +1,43 @@
1
- /**
2
- * Authentication Verify Code / Complete 2FA API Handler
3
- *
4
- * Handles 2FA verification and token updates after successful verification.
5
- * This handler is designed to be imported and used by Next.js applications
6
- * using the @payez/next-mvp package.
7
- *
8
- * @version 2.0
9
- * @requires Authentication (authenticated endpoint)
10
- */
11
- import { NextRequest, NextResponse } from 'next/server';
12
- interface VerifyCodeConfig {
13
- nextAuthSecret: string;
14
- }
15
- /**
16
- * Creates a verify-code/complete-2FA handler for Next.js API routes
17
- *
18
- * @param config Configuration for NextAuth
19
- * @returns Next.js POST handler function
20
- *
21
- * @example
22
- * ```typescript
23
- * // In your app's /app/api/auth/verify-code/route.ts
24
- * import { createVerifyCodeHandler } from '@payez/next-mvp/api-handlers/auth/verify-code';
25
- *
26
- * export const POST = createVerifyCodeHandler({
27
- * nextAuthSecret: process.env.NEXTAUTH_SECRET!
28
- * });
29
- * ```
30
- */
31
- export declare function createVerifyCodeHandler(config: VerifyCodeConfig): (req: NextRequest) => Promise<NextResponse<{
32
- success: boolean;
33
- message: string;
34
- }>>;
35
- /**
36
- * Default export for backward compatibility
37
- * Requires environment variable: NEXTAUTH_SECRET
38
- */
39
- export declare const POST: (req: NextRequest) => Promise<NextResponse<{
40
- success: boolean;
41
- message: string;
42
- }>>;
43
- export {};
1
+ /**
2
+ * Authentication Verify Code / Complete 2FA API Handler
3
+ *
4
+ * Handles 2FA verification and token updates after successful verification.
5
+ * This handler is designed to be imported and used by Next.js applications
6
+ * using the @payez/next-mvp package.
7
+ *
8
+ * @version 2.0
9
+ * @requires Authentication (authenticated endpoint)
10
+ */
11
+ import { NextRequest, NextResponse } from 'next/server';
12
+ interface VerifyCodeConfig {
13
+ nextAuthSecret?: string;
14
+ }
15
+ /**
16
+ * Creates a verify-code/complete-2FA handler for Next.js API routes
17
+ *
18
+ * @param config Configuration for NextAuth
19
+ * @returns Next.js POST handler function
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // In your app's /app/api/auth/verify-code/route.ts
24
+ * import { createVerifyCodeHandler } from '@payez/next-mvp/api-handlers/auth/verify-code';
25
+ *
26
+ * export const POST = createVerifyCodeHandler({
27
+ * nextAuthSecret: process.env.NEXTAUTH_SECRET!
28
+ * });
29
+ * ```
30
+ */
31
+ export declare function createVerifyCodeHandler(config: VerifyCodeConfig): (req: NextRequest) => Promise<NextResponse<{
32
+ success: boolean;
33
+ message: string;
34
+ }>>;
35
+ /**
36
+ * Default export for backward compatibility
37
+ * Requires environment variable: NEXTAUTH_SECRET
38
+ */
39
+ export declare const POST: (req: NextRequest) => Promise<NextResponse<{
40
+ success: boolean;
41
+ message: string;
42
+ }>>;
43
+ export {};