@@ -3,12 +3,21 @@ import { authService } from '../services/authServices.js';
33import { googleAuthService } from '../services/googleAuth.service.js' ;
44import { logger } from '../config/logger.js' ;
55import { AppError } from '../middlewares/errorHandller.js' ;
6- import { authSessionRepository } from '../repositories/authSessionRepository.js' ;
7- import { hashRefreshToken } from '../utils/jwtService.js' ;
86import { redis } from '../config/redis.js' ;
7+ import { hashRefreshToken } from '../utils/jwtService.js' ;
8+ import { authSessionRepository } from '../repositories/authSessionRepository.js' ;
99
1010const isProduction = process . env . NODE_ENV === 'production' ;
1111
12+ const cookieOptions = ( maxAge : number ) => ( {
13+ httpOnly : true ,
14+ secure : isProduction ,
15+ sameSite : ( isProduction ? 'none' : 'lax' ) as 'none' | 'lax' ,
16+ path : '/' ,
17+ maxAge,
18+ ...( isProduction && { domain : '.conferoo.in' } ) ,
19+ } ) ;
20+
1221export const register = async ( req : Request , res : Response ) => {
1322 const { email, password, fullName } = req . body ;
1423 const verificationToken = await authService . registerUser (
@@ -55,12 +64,6 @@ export const login = async (req: Request, res: Response) => {
5564 const { accessToken, refreshToken, role, userId } =
5665 await authService . loginUser ( email , password ) ;
5766
58- // ── Single-device login block ─────────────────────────────────────────────
59- // Check if this user already has an active socket (online:{userId} exists).
60- // Both services share the same Redis instance so this check is reliable.
61- // If online → reject with 409 and return userId so frontend can force logout.
62- // The user must force-logout the other device before they can log in here.
63- // ─────────────────────────────────────────────────────────────────────────
6467 const alreadyOnline = await redis . exists ( `online:${ userId } ` ) ;
6568 if ( alreadyOnline ) {
6669 logger . info ( `Login blocked — user ${ userId } already online` ) ;
@@ -74,29 +77,17 @@ export const login = async (req: Request, res: Response) => {
7477
7578 logger . info ( 'Login Succesfull' ) ;
7679
77- res . cookie ( 'refreshToken' , refreshToken , {
78- httpOnly : true ,
79- secure : false ,
80- sameSite : 'lax' ,
81- domain : 'localhost' ,
82- path : '/' ,
83- maxAge : 7 * 24 * 60 * 60 * 1000 ,
84- } ) ;
85-
86- res . cookie ( 'accessToken' , accessToken , {
87- httpOnly : true ,
88- secure : false ,
89- sameSite : 'lax' ,
90- domain : 'localhost' ,
91- path : '/' ,
92- maxAge : 24 * 60 * 60 * 1000 ,
93- } ) ;
80+ res . cookie (
81+ 'refreshToken' ,
82+ refreshToken ,
83+ cookieOptions ( 7 * 24 * 60 * 60 * 1000 )
84+ ) ;
85+ res . cookie ( 'accessToken' , accessToken , cookieOptions ( 24 * 60 * 60 * 1000 ) ) ;
9486
9587 res . status ( 200 ) . json ( {
9688 message : 'Login Successfully Completed' ,
9789 success : true ,
9890 role,
99- userId,
10091 } ) ;
10192} ;
10293
@@ -120,32 +111,33 @@ export const resendOtp = async (req: Request, res: Response) => {
120111export const googleLogin = async ( req : Request , res : Response ) => {
121112 const { idToken } = req . body ;
122113
123- const { accessToken, refreshToken } =
114+ const { accessToken, refreshToken, role , userId } =
124115 await googleAuthService . authenticate ( idToken ) ;
125116
126- logger . info ( 'Google login successful' ) ;
117+ const alreadyOnline = await redis . exists ( `online:${ userId } ` ) ;
118+ if ( alreadyOnline ) {
119+ logger . info ( `Login blocked — user ${ userId } already online` ) ;
120+ return res . status ( 409 ) . json ( {
121+ success : false ,
122+ message : 'You are already logged in on another device or tab.' ,
123+ code : 'ALREADY_LOGGED_IN' ,
124+ userId,
125+ } ) ;
126+ }
127127
128- res . cookie ( 'refreshToken' , refreshToken , {
129- httpOnly : true ,
130- secure : false ,
131- sameSite : 'lax' ,
132- domain : 'localhost' ,
133- path : '/' ,
134- maxAge : 7 * 24 * 60 * 60 * 1000 ,
135- } ) ;
128+ logger . info ( 'Google login successful' ) ;
136129
137- res . cookie ( 'accessToken' , accessToken , {
138- httpOnly : true ,
139- secure : false ,
140- sameSite : 'lax' ,
141- domain : 'localhost' ,
142- path : '/' ,
143- maxAge : 24 * 60 * 60 * 1000 ,
144- } ) ;
130+ res . cookie (
131+ 'refreshToken' ,
132+ refreshToken ,
133+ cookieOptions ( 7 * 24 * 60 * 60 * 1000 )
134+ ) ;
135+ res . cookie ( 'accessToken' , accessToken , cookieOptions ( 24 * 60 * 60 * 1000 ) ) ;
145136
146137 res . status ( 200 ) . json ( {
147138 success : true ,
148139 message : 'Google login successfully completed' ,
140+ role,
149141 } ) ;
150142} ;
151143
@@ -208,17 +200,16 @@ export const logout = async (req: Request, res: Response) => {
208200
209201 await authService . logoutUser ( refreshToken ) ;
210202
211- res . clearCookie ( 'refreshToken' , {
203+ const clearOptions = {
212204 httpOnly : true ,
213- sameSite : 'lax' ,
214205 secure : isProduction ,
215- } ) ;
206+ sameSite : ( isProduction ? 'none' : 'lax' ) as 'none' | 'lax' ,
207+ path : '/' ,
208+ ...( isProduction && { domain : '.conferoo.in' } ) ,
209+ } ;
216210
217- res . clearCookie ( 'accessToken' , {
218- httpOnly : true ,
219- sameSite : 'lax' ,
220- secure : isProduction ,
221- } ) ;
211+ res . clearCookie ( 'refreshToken' , clearOptions ) ;
212+ res . clearCookie ( 'accessToken' , clearOptions ) ;
222213
223214 res . status ( 200 ) . json ( {
224215 success : true ,
@@ -234,11 +225,7 @@ export const refresh = async (req: Request, res: Response) => {
234225
235226 const newAccessToken = await authService . refreshAccessToken ( refreshToken ) ;
236227
237- res . cookie ( 'accessToken' , newAccessToken , {
238- httpOnly : true ,
239- secure : isProduction ,
240- sameSite : 'lax' ,
241- } ) ;
228+ res . cookie ( 'accessToken' , newAccessToken , cookieOptions ( 24 * 60 * 60 * 1000 ) ) ;
242229
243230 res . status ( 200 ) . json ( {
244231 message : 'refresh succesfully' ,
@@ -257,4 +244,4 @@ export const resetPassword = async (req: Request, res: Response) => {
257244 const { token, newPassword } = req . body ;
258245 await authService . resetPassword ( token , newPassword ) ;
259246 res . json ( { message : 'Password updated successfully' } ) ;
260- } ;
247+ } ;
0 commit comments