diff --git a/src/modules/auth/guards/auth.guard.ts b/src/modules/auth/guards/auth.guard.ts index 884f07d..de0b9fd 100644 --- a/src/modules/auth/guards/auth.guard.ts +++ b/src/modules/auth/guards/auth.guard.ts @@ -26,6 +26,10 @@ export class AuthGuard implements CanActivate { try { const secret = this.configService.getOrThrow('JWT_SECRET'); const token = this.extractTokenFromHeader(request); + const slug = this.extractSlugFromHeader(request); + if (!slug) { + throw new UnauthorizedException('Slug is required'); + } if (!token) { throw new UnauthorizedException(); } @@ -38,6 +42,9 @@ export class AuthGuard implements CanActivate { this.logger.error('Invalid token payload structure', payload); throw new UnauthorizedException('Invalid token payload'); } + if (payload.slug !== slug) { + throw new UnauthorizedException('Invalid slug'); + } request['userId'] = payload.userId; request['restId'] = payload.restId; } catch { @@ -57,4 +64,8 @@ export class AuthGuard implements CanActivate { const [type, token] = request.headers.authorization?.split(' ') ?? []; return type === 'Bearer' ? token : undefined; } + private extractSlugFromHeader(request: Request): string | undefined { + const slug = request.headers['X-Slug'] as string; + return slug; + } } diff --git a/src/modules/auth/interfaces/IToken-payload.ts b/src/modules/auth/interfaces/IToken-payload.ts index 5603e41..457b2ca 100755 --- a/src/modules/auth/interfaces/IToken-payload.ts +++ b/src/modules/auth/interfaces/IToken-payload.ts @@ -1,6 +1,7 @@ export interface ITokenPayload { userId: string; restId: string; + slug: string; } export interface IAdminTokenPayload { diff --git a/src/modules/auth/services/auth.service.ts b/src/modules/auth/services/auth.service.ts index fe8ea6a..9a83e3a 100644 --- a/src/modules/auth/services/auth.service.ts +++ b/src/modules/auth/services/auth.service.ts @@ -28,9 +28,11 @@ export class AuthService { ) { this.OTP_EXPIRATION_TIME = this.configService.get('OTP_EXPIRATION_TIME') ?? 240; } + private userOtpKey(restaurantSlug: string, phone: string) { return `otp:${restaurantSlug}:${phone}`; } + private adminOtpKey(restaurantSlug: string, phone: string) { return `otp-admin:${restaurantSlug}:${phone}`; } @@ -64,7 +66,7 @@ export class AuthService { throw new BadRequestException(RestMessage.NOT_FOUND); } - const tokens = await this.tokensService.generateAccessAndRefreshToken(user.id, rest.id, false); + const tokens = await this.tokensService.generateAccessAndRefreshToken(user.id, rest.id, false, slug); const userResponse = UserLoginTransformer.transform(user, rest); @@ -93,7 +95,7 @@ export class AuthService { throw new BadRequestException(RestMessage.NOT_FOUND); } - const tokens = await this.tokensService.generateAccessAndRefreshToken(admin.id, rest.id, true); + const tokens = await this.tokensService.generateAccessAndRefreshToken(admin.id, rest.id, true, slug); const adminResponse = await AdminLoginTransformer.transform(admin, rest); diff --git a/src/modules/auth/services/tokens.service.ts b/src/modules/auth/services/tokens.service.ts index 0ea9ad8..a482ecf 100755 --- a/src/modules/auth/services/tokens.service.ts +++ b/src/modules/auth/services/tokens.service.ts @@ -8,6 +8,7 @@ import dayjs from 'dayjs'; import { AuthMessage } from '../../../common/enums/message.enum'; import { RefreshToken, RefreshTokenType } from '../entities/refresh-token.entity'; import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload'; +import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity'; @Injectable() export class TokensService { @@ -18,13 +19,13 @@ export class TokensService { private readonly em: EntityManager, ) {} - async generateAccessAndRefreshToken(ownerId: string, restaurantId: string, isAdmin: boolean) { + async generateAccessAndRefreshToken(ownerId: string, restaurantId: string, isAdmin: boolean, slug: string) { const refreshExpire = this.configService.getOrThrow('REFRESH_TOKEN_EXPIRE'); const accessExpire = this.configService.getOrThrow('JWT_EXPIRATION_TIME'); const payload: ITokenPayload | IAdminTokenPayload = isAdmin ? { adminId: ownerId, restId: restaurantId } - : { userId: ownerId, restId: restaurantId }; + : { userId: ownerId, restId: restaurantId, slug }; const accessToken = await this.generateAccessToken(payload, accessExpire); const refreshToken = this.generateRefreshToken(); @@ -78,12 +79,16 @@ export class TokensService { const ownerId = token.ownerId; const restId = token.restId; + const restaurant = await this.em.findOne(Restaurant, { id: restId }); + if (!restaurant) { + throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN); + } // Remove the old token this.em.remove(token); const isAdmin = token.type === RefreshTokenType.ADMIN; try { // Generate new tokens - const tokens = await this.generateAccessAndRefreshToken(ownerId, restId, isAdmin); + const tokens = await this.generateAccessAndRefreshToken(ownerId, restId, isAdmin, restaurant.slug); // Commit the transaction await this.em.flush();