From c196144d1cbb80002b8e251ce7605bf74ef7e3cb Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Mon, 2 Feb 2026 16:37:54 +0100 Subject: [PATCH] fix(mana-core-auth): return real refreshToken from signIn endpoint Same issue as sessionToToken - the signIn method was returning the session cookie token as refreshToken, but the /api/v1/auth/refresh endpoint expects the actual refreshToken field from the sessions table. Now signIn: - Fetches the session from database after Better Auth creates it - Uses existing refreshToken if available - Generates and stores a new refreshToken if missing - Returns the actual refreshToken that works with token refresh Co-Authored-By: Claude Opus 4.5 --- .../src/auth/services/better-auth.service.ts | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/services/mana-core-auth/src/auth/services/better-auth.service.ts b/services/mana-core-auth/src/auth/services/better-auth.service.ts index 3c602ddb9..035e9c08b 100644 --- a/services/mana-core-auth/src/auth/services/better-auth.service.ts +++ b/services/mana-core-auth/src/auth/services/better-auth.service.ts @@ -456,10 +456,50 @@ export class BetterAuthService { const { user } = result; - // Get session token (used as refresh token) + // Get session token (the cookie token, not the refresh token) const session = hasSession(result) ? result.session : null; const sessionToken = session?.token || (hasToken(result) ? result.token : ''); + // Get the actual refreshToken from the database + const db = getDb(this.databaseUrl); + const { sessions } = await import('../../db/schema'); + const { eq } = await import('drizzle-orm'); + const { nanoid } = await import('nanoid'); + + // Find the session by its token to get the real refreshToken + const [dbSession] = await db + .select() + .from(sessions) + .where(eq(sessions.token, sessionToken)) + .limit(1); + + let actualRefreshToken: string; + + if (dbSession?.refreshToken) { + // Session already has a refreshToken - use it + actualRefreshToken = dbSession.refreshToken; + this.logger.debug('SignIn: Using existing refreshToken from session'); + } else if (dbSession) { + // Session exists but no refreshToken - generate one and update the session + actualRefreshToken = nanoid(64); + const refreshTokenExpiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); // 7 days + + await db + .update(sessions) + .set({ + refreshToken: actualRefreshToken, + refreshTokenExpiresAt, + updatedAt: new Date(), + }) + .where(eq(sessions.id, dbSession.id)); + + this.logger.debug('SignIn: Generated new refreshToken for session'); + } else { + // No session found in DB - this shouldn't happen, but handle it + this.logger.warn('SignIn: Session not found in database, using session token as fallback'); + actualRefreshToken = sessionToken; + } + // Generate JWT access token using Better Auth's JWT plugin let accessToken = ''; try { @@ -501,7 +541,7 @@ export class BetterAuthService { role: (user as BetterAuthUser).role, }, accessToken, - refreshToken: sessionToken, + refreshToken: actualRefreshToken, expiresIn: 15 * 60, // 15 minutes in seconds }; } catch (error: unknown) {