npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@develop-x/nest-auth-context

v1.0.5

Published

## Overview

Readme

@develop-x/nest-auth-context

Overview

@develop-x/nest-auth-context is a NestJS package that provides user authentication context management for your applications. It extracts user information from request headers and makes it available throughout the request lifecycle via decorators and middleware.

Installation

npm install @develop-x/nest-auth-context

Features

  • User Context Middleware: Automatically extracts user information from request headers
  • Parameter Decorators: Easy access to current user data in controllers
  • Request Scoped: User context is available throughout the entire request lifecycle
  • Type Safe: Full TypeScript support with proper typing
  • Flexible: Works with various authentication schemes and user data formats

Usage

Module Import

Import the AuthContextModule in your application module:

import { Module } from '@nestjs/common';
import { AuthContextModule } from '@develop-x/nest-auth-context';

@Module({
  imports: [AuthContextModule],
})
export class AppModule {}

Middleware Configuration

Apply the user context middleware to extract user information from requests:

import { Module, MiddlewareConsumer } from '@nestjs/common';
import { UserContextMiddleware } from '@develop-x/nest-auth-context';

@Module({
  imports: [AuthContextModule],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(UserContextMiddleware)
      .forRoutes('*'); // Apply to all routes
  }
}

Using Decorators in Controllers

Use the provided decorators to access current user information:

import { Controller, Get, Post, Body } from '@nestjs/common';
import { CurrentUser, CurrentUserId } from '@develop-x/nest-auth-context';

@Controller('users')
export class UsersController {
  @Get('profile')
  getProfile(@CurrentUser() user: any) {
    return {
      message: 'User profile',
      user: user,
    };
  }

  @Get('dashboard')
  getDashboard(@CurrentUserId() userId: string) {
    return {
      message: `Dashboard for user ${userId}`,
      userId: userId,
    };
  }

  @Post('update')
  updateProfile(
    @CurrentUser() user: any,
    @CurrentUserId() userId: string,
    @Body() updateData: any
  ) {
    return {
      message: 'Profile updated',
      userId: userId,
      user: user,
      updateData: updateData,
    };
  }
}

API Reference

Decorators

@CurrentUser()

Extracts the complete user object from the request context.

Returns: any - The complete user object

Example:

@Get('profile')
getProfile(@CurrentUser() user: any) {
  console.log(user); // { id: '123', email: '[email protected]', roles: ['user'] }
  return user;
}

@CurrentUserId()

Extracts only the user ID from the request context.

Returns: string | undefined - The user ID or undefined if not available

Example:

@Get('orders')
getUserOrders(@CurrentUserId() userId: string) {
  if (!userId) {
    throw new UnauthorizedException('User not authenticated');
  }
  return this.orderService.getOrdersByUserId(userId);
}

Middleware

UserContextMiddleware

Middleware that extracts user information from request headers and attaches it to the request object.

Header Processing:

  • Looks for user information in request headers
  • Parses and validates user data
  • Attaches user object to request.user

Request Header Format

The middleware expects user information to be provided in request headers. The exact format depends on your authentication system, but typically includes:

// Example headers from an authentication gateway or proxy
{
  'x-user-id': '123',
  'x-user-email': '[email protected]',
  'x-user-roles': 'user,admin',
  // or a single header with JSON data
  'x-user-data': '{"id":"123","email":"[email protected]","roles":["user","admin"]}'
}

Advanced Usage

Custom User Type

Define a custom user interface for better type safety:

// types/user.interface.ts
export interface User {
  id: string;
  email: string;
  roles: string[];
  permissions: string[];
  organizationId?: string;
}

// controllers/users.controller.ts
import { Controller, Get } from '@nestjs/common';
import { CurrentUser, CurrentUserId } from '@develop-x/nest-auth-context';
import { User } from '../types/user.interface';

@Controller('users')
export class UsersController {
  @Get('profile')
  getProfile(@CurrentUser() user: User) {
    return {
      id: user.id,
      email: user.email,
      roles: user.roles,
    };
  }
}

Role-Based Access Control

Combine with guards for role-based access control:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!requiredRoles) {
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    return requiredRoles.some(role => user?.roles?.includes(role));
  }
}

// Usage in controller
import { UseGuards, SetMetadata } from '@nestjs/common';

@Controller('admin')
@UseGuards(RolesGuard)
export class AdminController {
  @Get('users')
  @SetMetadata('roles', ['admin'])
  getUsers(@CurrentUser() user: User) {
    return this.userService.getAllUsers();
  }
}

Service Integration

Access user context in services:

import { Injectable, Scope, Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class UserAwareService {
  constructor(@Inject(REQUEST) private request: Request) {}

  getCurrentUser() {
    return this.request.user;
  }

  getCurrentUserId(): string | undefined {
    return this.request.user?.id;
  }

  async getUserData() {
    const userId = this.getCurrentUserId();
    if (!userId) {
      throw new Error('User not authenticated');
    }
    
    return this.userRepository.findById(userId);
  }
}

Audit Logging

Automatically log user actions:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { LoggerService } from '@develop-x/nest-logger';

@Injectable()
export class AuditInterceptor implements NestInterceptor {
  constructor(private readonly logger: LoggerService) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const method = request.method;
    const url = request.url;

    return next.handle().pipe(
      tap(() => {
        this.logger.info('User action', {
          userId: user?.id,
          userEmail: user?.email,
          method,
          url,
          timestamp: new Date().toISOString(),
        });
      })
    );
  }
}

// Apply globally or to specific controllers
@UseInterceptors(AuditInterceptor)
@Controller('api')
export class ApiController {
  // ... controller methods
}

Integration Examples

With Authentication Guard

import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;

    if (!user || !user.id) {
      throw new UnauthorizedException('User not authenticated');
    }

    return true;
  }
}

// Usage
@Controller('protected')
@UseGuards(AuthGuard)
export class ProtectedController {
  @Get('data')
  getProtectedData(@CurrentUser() user: User) {
    return { message: 'Protected data', user };
  }
}

With API Gateway Integration

// When using with an API Gateway that forwards user information
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class GatewayUserMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    // Extract user info from gateway headers
    const userId = req.headers['x-gateway-user-id'] as string;
    const userEmail = req.headers['x-gateway-user-email'] as string;
    const userRoles = req.headers['x-gateway-user-roles'] as string;

    if (userId) {
      req.user = {
        id: userId,
        email: userEmail,
        roles: userRoles ? userRoles.split(',') : [],
      };
    }

    next();
  }
}

Multi-tenant Support

import { Injectable } from '@nestjs/common';
import { CurrentUser } from '@develop-x/nest-auth-context';

interface TenantUser {
  id: string;
  email: string;
  tenantId: string;
  roles: string[];
}

@Injectable()
export class TenantService {
  async getTenantData(@CurrentUser() user: TenantUser) {
    return this.dataService.getDataByTenant(user.tenantId);
  }

  async createResource(
    @CurrentUser() user: TenantUser,
    resourceData: any
  ) {
    return this.resourceService.create({
      ...resourceData,
      tenantId: user.tenantId,
      createdBy: user.id,
    });
  }
}

Testing

Unit Testing with User Context

import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';

describe('UsersController', () => {
  let controller: UsersController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [UsersController],
    }).compile();

    controller = module.get<UsersController>(UsersController);
  });

  it('should return user profile', () => {
    const mockUser = {
      id: '123',
      email: '[email protected]',
      roles: ['user'],
    };

    const result = controller.getProfile(mockUser);

    expect(result).toEqual({
      message: 'User profile',
      user: mockUser,
    });
  });

  it('should return dashboard for user', () => {
    const userId = '123';
    const result = controller.getDashboard(userId);

    expect(result).toEqual({
      message: 'Dashboard for user 123',
      userId: '123',
    });
  });
});

Integration Testing

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AuthContextModule, UserContextMiddleware } from '@develop-x/nest-auth-context';
import * as request from 'supertest';

describe('Auth Context (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AuthContextModule, AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    app.use(new UserContextMiddleware().use);
    await app.init();
  });

  it('should extract user from headers', () => {
    return request(app.getHttpServer())
      .get('/users/profile')
      .set('x-user-id', '123')
      .set('x-user-email', '[email protected]')
      .expect(200)
      .expect((res) => {
        expect(res.body.user).toBeDefined();
        expect(res.body.user.id).toBe('123');
      });
  });
});

Best Practices

  1. Type Safety: Define proper TypeScript interfaces for your user objects
  2. Validation: Validate user data extracted from headers
  3. Security: Never trust header data completely; validate against your user store
  4. Performance: Use request-scoped services when you need user context in services
  5. Error Handling: Handle cases where user information is missing or invalid
  6. Testing: Mock user context properly in your tests

Security Considerations

  1. Header Validation: Always validate user information from headers
  2. Authorization: Use additional guards for authorization checks
  3. Sensitive Data: Don't include sensitive information in user context
  4. Token Verification: If using tokens, verify them before trusting user data

Dependencies

  • @nestjs/common: NestJS common utilities
  • express: Express.js types for request/response handling

License

ISC

Support

For issues and questions, please refer to the project repository or contact the development team.