@payez/next-mvp 4.0.8 → 4.0.10

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.
@@ -42,6 +42,7 @@ export declare function createBetterAuthInstance(idpConfig: IDPClientConfig): im
42
42
  cookieCache: {
43
43
  enabled: true;
44
44
  maxAge: number;
45
+ refreshCache: false;
45
46
  };
46
47
  };
47
48
  advanced: {
@@ -97,6 +97,7 @@ function createBetterAuthInstance(idpConfig) {
97
97
  cookieCache: {
98
98
  enabled: true,
99
99
  maxAge: 300,
100
+ refreshCache: false,
100
101
  },
101
102
  },
102
103
  // Cookie prefix must match slim-middleware expectations ({slug}.session-token)
@@ -25,6 +25,8 @@ exports.ensureFreshToken = ensureFreshToken;
25
25
  exports.getFreshAuthHeader = getFreshAuthHeader;
26
26
  const session_store_1 = require("./session-store");
27
27
  const auth_1 = require("../server/auth");
28
+ const redis_1 = require("./redis");
29
+ const app_slug_1 = require("./app-slug");
28
30
  // 5 minute threshold for "needs refresh" - matches refresh handler pattern
29
31
  const REFRESH_THRESHOLD_MS = 5 * 60 * 1000;
30
32
  // Concurrent refresh handling configuration
@@ -220,8 +222,45 @@ async function ensureFreshToken(request) {
220
222
  };
221
223
  }
222
224
  const sessionToken = betterAuthSession.session.token;
223
- // 2. Get session data from Redis
225
+ // 2. Get session data from Redis (legacy prefix), or Better Auth's secondary storage
224
226
  let sessionData = await (0, session_store_1.getSession)(sessionToken);
227
+ if (!sessionData) {
228
+ // Try Better Auth's secondaryStorage key (ba:{slug}:{token})
229
+ try {
230
+ const baKey = `ba:${(0, app_slug_1.getAppSlug)()}:${sessionToken}`;
231
+ const baRaw = await (0, redis_1.getRedis)().get(baKey);
232
+ if (baRaw) {
233
+ const baSession = JSON.parse(baRaw);
234
+ // Map Better Auth session to SessionData
235
+ sessionData = {
236
+ userId: baSession.user?.id || betterAuthSession.user?.id || '',
237
+ email: baSession.user?.email || betterAuthSession.user?.email || '',
238
+ name: baSession.user?.name || betterAuthSession.user?.name,
239
+ roles: [],
240
+ idpAccessTokenExpires: baSession.session?.expiresAt
241
+ ? new Date(baSession.session.expiresAt).getTime()
242
+ : Date.now() + 24 * 60 * 60 * 1000,
243
+ mfaVerified: true,
244
+ oauthProvider: 'google',
245
+ };
246
+ }
247
+ }
248
+ catch { /* Redis unavailable */ }
249
+ }
250
+ if (!sessionData) {
251
+ // Last resort: build from Better Auth in-memory session
252
+ if (betterAuthSession.user) {
253
+ sessionData = {
254
+ userId: betterAuthSession.user.id || '',
255
+ email: betterAuthSession.user.email || '',
256
+ name: betterAuthSession.user.name,
257
+ roles: [],
258
+ idpAccessTokenExpires: Date.now() + 24 * 60 * 60 * 1000,
259
+ mfaVerified: true,
260
+ oauthProvider: 'google',
261
+ };
262
+ }
263
+ }
225
264
  if (!sessionData) {
226
265
  return {
227
266
  success: false,
@@ -313,17 +352,10 @@ async function ensureFreshToken(request) {
313
352
  // immediately available in Vibe's JWKS cache
314
353
  await delay(KEY_PROPAGATION_DELAY_MS);
315
354
  }
316
- // 6. Validate we have a token
317
- if (!sessionData.idpAccessToken) {
318
- return {
319
- success: false,
320
- error: 'NO_TOKEN',
321
- message: 'No access token available',
322
- };
323
- }
355
+ // 6. Return session accessToken may be empty for social-only OAuth sessions
324
356
  return {
325
357
  success: true,
326
- accessToken: sessionData.idpAccessToken,
358
+ accessToken: sessionData.idpAccessToken || '',
327
359
  sessionData,
328
360
  };
329
361
  }
@@ -25,6 +25,7 @@ export declare function getAuthInstance(): Promise<import("better-auth/types").A
25
25
  cookieCache: {
26
26
  enabled: true;
27
27
  maxAge: number;
28
+ refreshCache: false;
28
29
  };
29
30
  };
30
31
  advanced: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payez/next-mvp",
3
- "version": "4.0.8",
3
+ "version": "4.0.10",
4
4
  "sideEffects": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -105,6 +105,7 @@ export function createBetterAuthInstance(idpConfig: IDPClientConfig) {
105
105
  cookieCache: {
106
106
  enabled: true,
107
107
  maxAge: 300,
108
+ refreshCache: false,
108
109
  },
109
110
  },
110
111
 
@@ -23,6 +23,8 @@
23
23
  import { NextRequest } from 'next/server';
24
24
  import { getSession as getRedisSession, SessionData } from './session-store';
25
25
  import { getSession as getBetterAuthSession } from '../server/auth';
26
+ import { getRedis } from './redis';
27
+ import { getAppSlug } from './app-slug';
26
28
 
27
29
  // 5 minute threshold for "needs refresh" - matches refresh handler pattern
28
30
  const REFRESH_THRESHOLD_MS = 5 * 60 * 1000;
@@ -282,9 +284,47 @@ export async function ensureFreshToken(
282
284
 
283
285
  const sessionToken = betterAuthSession.session.token;
284
286
 
285
- // 2. Get session data from Redis
287
+ // 2. Get session data from Redis (legacy prefix), or Better Auth's secondary storage
286
288
  let sessionData = await getRedisSession(sessionToken);
287
289
 
290
+ if (!sessionData) {
291
+ // Try Better Auth's secondaryStorage key (ba:{slug}:{token})
292
+ try {
293
+ const baKey = `ba:${getAppSlug()}:${sessionToken}`;
294
+ const baRaw = await getRedis().get(baKey);
295
+ if (baRaw) {
296
+ const baSession = JSON.parse(baRaw);
297
+ // Map Better Auth session to SessionData
298
+ sessionData = {
299
+ userId: baSession.user?.id || betterAuthSession.user?.id || '',
300
+ email: baSession.user?.email || betterAuthSession.user?.email || '',
301
+ name: baSession.user?.name || betterAuthSession.user?.name,
302
+ roles: [],
303
+ idpAccessTokenExpires: baSession.session?.expiresAt
304
+ ? new Date(baSession.session.expiresAt).getTime()
305
+ : Date.now() + 24 * 60 * 60 * 1000,
306
+ mfaVerified: true,
307
+ oauthProvider: 'google',
308
+ } as SessionData;
309
+ }
310
+ } catch { /* Redis unavailable */ }
311
+ }
312
+
313
+ if (!sessionData) {
314
+ // Last resort: build from Better Auth in-memory session
315
+ if (betterAuthSession.user) {
316
+ sessionData = {
317
+ userId: betterAuthSession.user.id || '',
318
+ email: betterAuthSession.user.email || '',
319
+ name: betterAuthSession.user.name,
320
+ roles: [],
321
+ idpAccessTokenExpires: Date.now() + 24 * 60 * 60 * 1000,
322
+ mfaVerified: true,
323
+ oauthProvider: 'google',
324
+ } as SessionData;
325
+ }
326
+ }
327
+
288
328
  if (!sessionData) {
289
329
  return {
290
330
  success: false,
@@ -386,18 +426,10 @@ export async function ensureFreshToken(
386
426
  await delay(KEY_PROPAGATION_DELAY_MS);
387
427
  }
388
428
 
389
- // 6. Validate we have a token
390
- if (!sessionData.idpAccessToken) {
391
- return {
392
- success: false,
393
- error: 'NO_TOKEN',
394
- message: 'No access token available',
395
- };
396
- }
397
-
429
+ // 6. Return session accessToken may be empty for social-only OAuth sessions
398
430
  return {
399
431
  success: true,
400
- accessToken: sessionData.idpAccessToken,
432
+ accessToken: sessionData.idpAccessToken || '',
401
433
  sessionData,
402
434
  };
403
435
  } catch (error) {