From fee16c3b2b8e483e675bf9567a1b30b07f2320a9 Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Sat, 21 Feb 2026 15:52:22 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20Add=20license=5Fid=20to=20JWT=20payload?= =?UTF-8?q?=20=E2=80=94=20unblocks=20all=20tenant-scoped=20operations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JWT was missing license_id, causing @CurrentTenant() to throw 401 on every protected route. Now generateTokens() accepts a licenseId param, and all three callers (register, login, refresh) look up the user's license and pass it through. Co-Authored-By: Claude Opus 4.6 --- backend-nest/src/modules/auth/auth.service.ts | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/backend-nest/src/modules/auth/auth.service.ts b/backend-nest/src/modules/auth/auth.service.ts index d001f32..1c96fe2 100644 --- a/backend-nest/src/modules/auth/auth.service.ts +++ b/backend-nest/src/modules/auth/auth.service.ts @@ -80,8 +80,8 @@ export class AuthService { await this.licenseRepository.save(license); - // Generate tokens - const tokens = await this.generateTokens(user); + // Generate tokens (include license_id for tenant-scoped operations) + const tokens = await this.generateTokens(user, license.id); return { ...tokens, @@ -144,14 +144,14 @@ export class AuthService { } } - // Generate tokens - const tokens = await this.generateTokens(user); - - // Get user's license + // Get user's license (needed for JWT license_id claim) const license = await this.licenseRepository.findOne({ where: { owner_user_id: user.id }, }); + // Generate tokens + const tokens = await this.generateTokens(user, license?.id); + return { ...tokens, requires_totp: false, @@ -191,8 +191,13 @@ export class AuthService { throw new UnauthorizedException('User not found'); } + // Look up license for JWT claim + const license = await this.licenseRepository.findOne({ + where: { owner_user_id: user.id }, + }); + // Generate new token pair (rotating refresh tokens) - const tokens = await this.generateTokens(user); + const tokens = await this.generateTokens(user, license?.id); return { access_token: tokens.access_token, @@ -332,14 +337,18 @@ export class AuthService { // Helper methods - private async generateTokens(user: User) { - const payload = { + private async generateTokens(user: User, licenseId?: string) { + const payload: Record = { sub: user.id, email: user.email, username: user.username, is_super_admin: user.is_super_admin, }; + if (licenseId) { + payload.license_id = licenseId; + } + const accessToken = await this.jwtService.signAsync(payload, { secret: this.configService.get('jwt.secret'), expiresIn: this.configService.get('jwt.accessExpirySeconds') || 900,