Package Exports
- @katalysttech/auth
- @katalysttech/auth/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@katalysttech/auth) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@katalyst/auth
A flexible and feature-rich authentication module for NestJS applications with support for JWT tokens, refresh tokens, multiple sessions, and various storage options.
cd existing_repo git remote add origin https://ntgitlab.novatechset.com/katalysttech-eco-system/auth-package.git git branch -M main git push -uf origin main
Features
- 🔐 JWT-based authentication
- 🔄 Refresh token support
- 📱 Multiple device sessions
- 💾 TypeORM and Redis storage support
- 🔒 Password hashing utilities
- 👥 Session management
- 🛡️ Route protection
- ⚙️ Highly configurable
Installation
npm install @katalyst/authDependencies
Based on your storage choice, install the required dependencies:
For TypeORM storage:
npm install typeorm @nestjs/typeormFor Redis storage:
npm install ioredisConfiguration
1. Module Setup
Synchronous Configuration
import { Module } from '@nestjs/common';
import { AuthModule } from '@katalyst/auth';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RefreshToken } from './entities/refresh-token.entity';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'your_username',
password: 'your_password',
database: 'your_database',
entities: [RefreshToken],
synchronize: true, // set to false in production
}),
AuthModule.register({
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: '15m',
},
refreshToken: {
secret: process.env.REFRESH_TOKEN_SECRET,
expiresIn: '7d',
maxActiveSessions: 5, // Optional: limit active sessions per user
storage: {
type: 'typeorm',
entity: RefreshToken,
}
},
findUserById: async (id) => {
// Implement your user lookup logic
return await userRepository.findOne({ where: { id } });
},
findUserByUsername: async (username) => {
// Implement your user lookup logic
return await userRepository.findOne({ where: { username } });
},
userFields: {
idField: 'id',
usernameField: 'username',
passwordField: 'password',
tokenFields: ['role'] // Additional fields to include in JWT payload
}
}),
],
})
export class AppModule {}Async Configuration
import { Module } from '@nestjs/common';
import { AuthModule } from '@katalyst/auth';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
AuthModule.registerAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
jwt: {
secret: configService.get('JWT_SECRET'),
expiresIn: configService.get('JWT_EXPIRES_IN'),
},
refreshToken: {
secret: configService.get('REFRESH_TOKEN_SECRET'),
expiresIn: configService.get('REFRESH_TOKEN_EXPIRES_IN'),
maxActiveSessions: configService.get('MAX_ACTIVE_SESSIONS'),
storage: {
type: 'typeorm',
entity: RefreshToken,
}
},
// ... other config
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}2. Entity Setup (For TypeORM)
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn } from 'typeorm';
@Entity('refresh_tokens')
export class RefreshToken {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
userId: string;
@Column()
tokenId: string;
@Column()
expiresAt: Date;
@Column({ default: false })
isRevoked: boolean;
@CreateDateColumn()
createdAt: Date;
@Column('json', { nullable: true })
deviceInfo: any;
}Important Notes About Entity Setup
- The
idfield must be of typestringto match the package's requirements - Use
@PrimaryGeneratedColumn('uuid')for string IDs - If you need to use numeric IDs, you'll need to convert them to strings in your entity
Example with Numeric ID (if required)
@Entity('refresh_tokens')
export class RefreshToken {
@PrimaryGeneratedColumn('increment')
@Transform(({ value }) => value.toString())
id: string;
// ... other fields
}Troubleshooting
Common Issues
ID Type Mismatch If you see the error: "The types of '(new refreshToken.storage.entity(...)).id' are incompatible between these types. Type 'number' is not assignable to type 'string'", you need to ensure your RefreshToken entity's
idfield is of typestring. See the Entity Setup section above for solutions.Storage Configuration When using TypeORM storage, make sure to:
- Pass the correct DataSource instance
- Use the correct entity type
- Configure the proper ID field type
Usage
1. Authentication Controller
import { Controller, Post, Body, Get, UseGuards, Request } from '@nestjs/common';
import { AuthService, AuthGuard } from '@katalyst/auth';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('login')
async login(@Body() credentials: { username: string; password: string }) {
return await this.authService.login(credentials.username, credentials.password);
}
@Post('refresh')
async refresh(@Body() body: { refreshToken: string }) {
return await this.authService.refreshToken(body.refreshToken);
}
@Get('sessions')
@UseGuards(AuthGuard)
async getSessions(@Request() req: any) {
return await this.authService.getActiveSessions(req.user.sub);
}
@Post('logout')
@UseGuards(AuthGuard)
async logout(@Request() req: any) {
await this.authService.logout(req.user.sub, req.user.tokenId);
return { message: 'Logged out successfully' };
}
@Post('logout-all')
@UseGuards(AuthGuard)
async logoutAll(@Request() req: any) {
await this.authService.logoutAll(req.user.sub);
return { message: 'Logged out from all devices' };
}
}2. Protecting Routes
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@katalyst/auth';
@Controller('protected')
@UseGuards(AuthGuard)
export class ProtectedController {
@Get()
getProtectedData() {
return { message: 'This is protected data' };
}
}3. Password Utilities
import { Injectable } from '@nestjs/common';
import { PasswordService } from '@katalyst/auth';
@Injectable()
export class UserService {
constructor(private readonly passwordService: PasswordService) {}
async createUser(username: string, password: string) {
const hashedPassword = await this.passwordService.hashPassword(password);
// Save user with hashed password
}
async validatePassword(plainPassword: string, hashedPassword: string) {
return await this.passwordService.comparePassword(plainPassword, hashedPassword);
}
}4. Session Management
import { Controller, Get, Post, UseGuards, Request, Param } from '@nestjs/common';
import { AuthService, AuthGuard } from '@katalyst/auth';
@Controller('sessions')
@UseGuards(AuthGuard)
export class SessionController {
constructor(private readonly authService: AuthService) {}
@Get()
async getActiveSessions(@Request() req: any) {
return await this.authService.getActiveSessions(req.user.sub);
}
@Post('revoke/:tokenId')
async revokeSession(@Request() req: any, @Param('tokenId') tokenId: string) {
await this.authService.revokeToken(req.user.sub, tokenId);
return { message: 'Session revoked successfully' };
}
}Environment Variables
JWT_SECRET=your_jwt_secret_key
JWT_EXPIRES_IN=15m
REFRESH_TOKEN_SECRET=your_refresh_token_secret
REFRESH_TOKEN_EXPIRES_IN=7d
MAX_ACTIVE_SESSIONS=5API Response Types
Login Response
interface AuthTokens {
accessToken: string;
refreshToken: string;
expiresIn: number;
}Active Session Response
interface Session {
id: string;
createdAt: Date;
expiresAt: Date;
deviceInfo?: {
userAgent?: string;
ip?: string;
// ... other device info
};
}Error Handling
The module throws standard NestJS exceptions:
UnauthorizedException: Invalid credentials, invalid token, or revoked tokenBadRequestException: Invalid refresh token or missing required fieldsForbiddenException: Token revoked or session limit exceeded
Best Practices
Security
- Store secrets in environment variables
- Use strong secret keys
- Set appropriate token expiration times
- Implement rate limiting for auth endpoints
Token Storage
- Use secure storage for refresh tokens
- Implement regular token cleanup
- Monitor active sessions
Error Handling
- Implement proper error handling in your controllers
- Log authentication failures
- Provide clear error messages to users
Contributing
Contributions are welcome! Please read our contributing guidelines for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.