fix: Add license_id to JWT payload — unblocks all tenant-scoped operations
All checks were successful
Test Asgard Runner / test (push) Successful in 3s
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:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user