From db9510a6a6455b91f3324cc7f784423f790dc7dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 07:59:11 +0000 Subject: [PATCH 1/4] Initial plan From c65bb24ebbf332328ba127d2b1163d3d756d6549 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 08:03:15 +0000 Subject: [PATCH 2/4] feat: add audit logging for service impersonation events Co-authored-by: dipesh-rumsan <203831631+dipesh-rumsan@users.noreply.github.com> --- .../src/lib/auths/guard/hybrid-jwt.guard.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts index 7ed5f4e..0b62c34 100644 --- a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts +++ b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts @@ -2,6 +2,7 @@ import { CanActivate, ExecutionContext, Injectable, + Logger, UnauthorizedException, } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; @@ -23,6 +24,8 @@ import { getSecret } from '../../utils/config.utils'; */ @Injectable() export class HybridJwtGuard implements CanActivate { + private readonly logger = new Logger(HybridJwtGuard.name); + constructor( private jwtService: JwtService, private prisma: PrismaService, @@ -78,6 +81,12 @@ export class HybridJwtGuard implements CanActivate { if (impersonateId) { if (!serviceClient.canImpersonate) { + // Log failed impersonation attempt + this.logger.warn( + `Service impersonation denied: service="${payload.serviceName}" ` + + `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + + `reason="Service not allowed to impersonate" ip="${request.ip || 'unknown'}"`, + ); throw new UnauthorizedException( 'This service is not allowed to impersonate users', ); @@ -85,6 +94,12 @@ export class HybridJwtGuard implements CanActivate { const user = await this.loadUserById(impersonateId); if (!user) { + // Log failed impersonation attempt + this.logger.warn( + `Service impersonation denied: service="${payload.serviceName}" ` + + `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + + `reason="User not found" ip="${request.ip || 'unknown'}"`, + ); throw new UnauthorizedException('Impersonated user not found'); } @@ -101,12 +116,28 @@ export class HybridJwtGuard implements CanActivate { ); if (!canImpersonate) { + // Log failed impersonation attempt + this.logger.warn( + `Service impersonation denied: service="${payload.serviceName}" ` + + `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + + `userId="${user.id}" userRoles="${userRoleNames.join(',')}" ` + + `reason="User roles not allowed" ip="${request.ip || 'unknown'}"`, + ); throw new UnauthorizedException( 'Service not allowed to impersonate users with these roles', ); } } + // Log successful impersonation + this.logger.log( + `Service impersonation granted: service="${payload.serviceName}" ` + + `clientId="${payload.clientId}" impersonatedUser="${user.uuid}" ` + + `userId="${user.id}" userName="${user.name}" userEmail="${user.email || 'none'}" ` + + `userRoles="${userRoleNames.join(',')}" ip="${request.ip || 'unknown'}" ` + + `userAgent="${request.headers['user-agent'] || 'unknown'}"`, + ); + request.user = { id: user.id, userId: user.id, From d88b862297205ea53c7ae7f306a525ea25772ec2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 08:04:44 +0000 Subject: [PATCH 3/4] refactor: reduce PII in audit logs and add logger documentation Co-authored-by: dipesh-rumsan <203831631+dipesh-rumsan@users.noreply.github.com> --- libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts index 0b62c34..42f12b1 100644 --- a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts +++ b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts @@ -24,6 +24,10 @@ import { getSecret } from '../../utils/config.utils'; */ @Injectable() export class HybridJwtGuard implements CanActivate { + /** + * Logger for audit logging of service impersonation events. + * Tracks both successful and failed impersonation attempts for security monitoring. + */ private readonly logger = new Logger(HybridJwtGuard.name); constructor( @@ -133,7 +137,6 @@ export class HybridJwtGuard implements CanActivate { this.logger.log( `Service impersonation granted: service="${payload.serviceName}" ` + `clientId="${payload.clientId}" impersonatedUser="${user.uuid}" ` + - `userId="${user.id}" userName="${user.name}" userEmail="${user.email || 'none'}" ` + `userRoles="${userRoleNames.join(',')}" ip="${request.ip || 'unknown'}" ` + `userAgent="${request.headers['user-agent'] || 'unknown'}"`, ); From cadd312acfe9dfc0dd36d26fb5b6dd8a2ddf45a6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 30 Jan 2026 08:06:21 +0000 Subject: [PATCH 4/4] refactor: simplify log format and remove sensitive ID exposure Co-authored-by: dipesh-rumsan <203831631+dipesh-rumsan@users.noreply.github.com> --- .../src/lib/auths/guard/hybrid-jwt.guard.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts index 42f12b1..c6a3922 100644 --- a/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts +++ b/libs/user/src/lib/auths/guard/hybrid-jwt.guard.ts @@ -87,9 +87,7 @@ export class HybridJwtGuard implements CanActivate { if (!serviceClient.canImpersonate) { // Log failed impersonation attempt this.logger.warn( - `Service impersonation denied: service="${payload.serviceName}" ` + - `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + - `reason="Service not allowed to impersonate" ip="${request.ip || 'unknown'}"`, + `Service impersonation denied - ${payload.serviceName}: service not allowed to impersonate`, ); throw new UnauthorizedException( 'This service is not allowed to impersonate users', @@ -100,9 +98,7 @@ export class HybridJwtGuard implements CanActivate { if (!user) { // Log failed impersonation attempt this.logger.warn( - `Service impersonation denied: service="${payload.serviceName}" ` + - `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + - `reason="User not found" ip="${request.ip || 'unknown'}"`, + `Service impersonation denied - ${payload.serviceName}: user not found`, ); throw new UnauthorizedException('Impersonated user not found'); } @@ -122,10 +118,7 @@ export class HybridJwtGuard implements CanActivate { if (!canImpersonate) { // Log failed impersonation attempt this.logger.warn( - `Service impersonation denied: service="${payload.serviceName}" ` + - `clientId="${payload.clientId}" impersonateId="${impersonateId}" ` + - `userId="${user.id}" userRoles="${userRoleNames.join(',')}" ` + - `reason="User roles not allowed" ip="${request.ip || 'unknown'}"`, + `Service impersonation denied - ${payload.serviceName}: user ${user.uuid} roles not allowed`, ); throw new UnauthorizedException( 'Service not allowed to impersonate users with these roles', @@ -135,10 +128,7 @@ export class HybridJwtGuard implements CanActivate { // Log successful impersonation this.logger.log( - `Service impersonation granted: service="${payload.serviceName}" ` + - `clientId="${payload.clientId}" impersonatedUser="${user.uuid}" ` + - `userRoles="${userRoleNames.join(',')}" ip="${request.ip || 'unknown'}" ` + - `userAgent="${request.headers['user-agent'] || 'unknown'}"`, + `Service impersonation granted - ${payload.serviceName}: user ${user.uuid} with roles ${userRoleNames.join(',')}`, ); request.user = {