fix: Add license_id to JWT payload — unblocks all tenant-scoped operations
All checks were successful
Test Asgard Runner / test (push) Successful in 3s

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 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-02-21 15:52:22 -05:00
parent 1b12664d22
commit fee16c3b2b

View File

@@ -80,8 +80,8 @@ export class AuthService {
await this.licenseRepository.save(license); await this.licenseRepository.save(license);
// Generate tokens // Generate tokens (include license_id for tenant-scoped operations)
const tokens = await this.generateTokens(user); const tokens = await this.generateTokens(user, license.id);
return { return {
...tokens, ...tokens,
@@ -144,14 +144,14 @@ export class AuthService {
} }
} }
// Generate tokens // Get user's license (needed for JWT license_id claim)
const tokens = await this.generateTokens(user);
// Get user's license
const license = await this.licenseRepository.findOne({ const license = await this.licenseRepository.findOne({
where: { owner_user_id: user.id }, where: { owner_user_id: user.id },
}); });
// Generate tokens
const tokens = await this.generateTokens(user, license?.id);
return { return {
...tokens, ...tokens,
requires_totp: false, requires_totp: false,
@@ -191,8 +191,13 @@ export class AuthService {
throw new UnauthorizedException('User not found'); 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) // Generate new token pair (rotating refresh tokens)
const tokens = await this.generateTokens(user); const tokens = await this.generateTokens(user, license?.id);
return { return {
access_token: tokens.access_token, access_token: tokens.access_token,
@@ -332,14 +337,18 @@ export class AuthService {
// Helper methods // Helper methods
private async generateTokens(user: User) { private async generateTokens(user: User, licenseId?: string) {
const payload = { const payload: Record<string, unknown> = {
sub: user.id, sub: user.id,
email: user.email, email: user.email,
username: user.username, username: user.username,
is_super_admin: user.is_super_admin, is_super_admin: user.is_super_admin,
}; };
if (licenseId) {
payload.license_id = licenseId;
}
const accessToken = await this.jwtService.signAsync(payload, { const accessToken = await this.jwtService.signAsync(payload, {
secret: this.configService.get<string>('jwt.secret'), secret: this.configService.get<string>('jwt.secret'),
expiresIn: this.configService.get<number>('jwt.accessExpirySeconds') || 900, expiresIn: this.configService.get<number>('jwt.accessExpirySeconds') || 900,