@bitwild/rockets-server
v0.1.0-dev.8
Published
Rockets Server
Readme
Rockets SDK Documentation
Project
Table of Contents
Introduction
Overview
The Rockets SDK is a comprehensive, enterprise-grade toolkit for building secure and scalable NestJS applications. It provides a unified solution that combines authentication, user management, OTP verification, email notifications, and API documentation into a single, cohesive package.
Built with TypeScript and following NestJS best practices, the Rockets SDK eliminates the complexity of setting up authentication systems while maintaining flexibility for customization and extension.
Key Features
- 🔐 Complete Authentication System: JWT tokens, local authentication, refresh tokens, and password recovery
- 🔗 OAuth Integration: Support for Google, GitHub, and Apple OAuth providers by default, with custom providers support
- 👥 User Management: Full CRUD operations, profile management, and password history
- 📱 OTP Support: One-time password generation and validation for secure authentication
- 📧 Email Notifications: Built-in email service with template support
- 📚 API Documentation: Automatic Swagger/OpenAPI documentation generation
- 🔧 Highly Configurable: Extensive configuration options for all modules
- 🏗️ Modular Architecture: Use only what you need, extend what you want
- 🛡️ Type Safety: Full TypeScript support with comprehensive interfaces
- 🧪 Testing Support: Complete testing utilities and fixtures including e2e tests
- 🔌 Adapter Pattern: Support for multiple database adapters
Installation
⚠️ CRITICAL: Alpha Version Issue:
The current alpha version (7.0.0-alpha.6) has a dependency injection issue with AuthJwtGuard that prevents the minimal setup from working. This is a known issue being investigated.
Version Requirements:
- NestJS:
^10.0.0 - Node.js:
>=18.0.0 - TypeScript:
>=4.8.0
Let's create a new NestJS project:
npx @nestjs/cli@10 new my-app-with-rockets --package-manager yarn --language TypeScript --strictInstall the Rockets SDK and all required dependencies:
yarn add @bitwild/rockets-server @concepta/nestjs-typeorm-ext \
@concepta/nestjs-common typeorm @nestjs/typeorm @nestjs/config \
@nestjs/swagger class-transformer class-validator sqlite3Tutorial
Quick Start
This tutorial will guide you through setting up a complete authentication system with the Rockets SDK in just a few steps. We'll use SQLite in-memory database for instant setup without any configuration.
Basic Setup
Step 1: Create Your Entities
First, create the required database entities by extending the base entities provided by the SDK:
// entities/user.entity.ts
import { Entity, OneToMany } from 'typeorm';
import { UserSqliteEntity } from '@concepta/nestjs-typeorm-ext';
import { UserOtpEntity } from './user-otp.entity';
import { FederatedEntity } from './federated.entity';
@Entity()
export class UserEntity extends UserSqliteEntity {
@OneToMany(() => UserOtpEntity, (userOtp) => userOtp.assignee)
userOtps?: UserOtpEntity[];
@OneToMany(() => FederatedEntity, (federated) => federated.assignee)
federatedAccounts?: FederatedEntity[];
}// entities/user-otp.entity.ts
import { Entity, ManyToOne } from 'typeorm';
import { ReferenceIdInterface } from '@concepta/nestjs-common';
import { OtpSqliteEntity } from '@concepta/nestjs-typeorm-ext';
import { UserEntity } from './user.entity';
@Entity()
export class UserOtpEntity extends OtpSqliteEntity {
@ManyToOne(() => UserEntity, (user) => user.userOtps)
assignee!: ReferenceIdInterface;
}// entities/federated.entity.ts
import { Entity, ManyToOne } from 'typeorm';
import { ReferenceIdInterface } from '@concepta/nestjs-common';
import { FederatedSqliteEntity } from '@concepta/nestjs-typeorm-ext';
import { UserEntity } from './user.entity';
@Entity()
export class FederatedEntity extends FederatedSqliteEntity {
@ManyToOne(() => UserEntity, (user) => user.federatedAccounts)
assignee!: ReferenceIdInterface;
}Step 2: Set Up Environment Variables (Production Only)
For production, create a .env file with JWT secrets:
# Required for production
JWT_MODULE_ACCESS_SECRET=your-super-secret-jwt-access-key-here
# Optional - defaults to access secret if not provided
JWT_MODULE_REFRESH_SECRET=your-super-secret-jwt-refresh-key-here
NODE_ENV=developmentNote: In development, JWT secrets are auto-generated if not provided.
Step 3: Configure Your Module
Create your main application module with the minimal Rockets SDK setup:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RocketsServerModule } from '@bitwild/rockets-server';
import { TypeOrmExtModule } from '@concepta/nestjs-typeorm-ext';
import { UserEntity } from './entities/user.entity';
import { UserOtpEntity } from './entities/user-otp.entity';
import { FederatedEntity } from './entities/federated.entity';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
}),
// Database configuration - SQLite in-memory for easy testing
TypeOrmExtModule.forRoot({
type: 'sqlite',
database: ':memory:', // In-memory database - no files created
synchronize: true, // Auto-create tables (dev only)
autoLoadEntities: true,
logging: false, // Set to true to see SQL queries
entities: [UserEntity, UserOtpEntity, FederatedEntity],
}),
// Rockets SDK configuration - minimal setup
RocketsServerModule.forRootAsync({
imports: [
TypeOrmModule.forFeature([UserEntity]),
TypeOrmExtModule.forFeature({
user: { entity: UserEntity },
role: { entity: RoleEntity },
userRole: { entity: UserRoleEntity },
userOtp: { entity: UserOtpEntity },
federated: { entity: FederatedEntity },
}),
],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
// Required services
services: {
mailerService: {
sendMail: (options: any) => {
console.log('📧 Email would be sent:', {
to: options.to,
subject: options.subject,
// Don't log the full content in examples
});
return Promise.resolve();
},
},
},
// Email and OTP settings
settings: {
email: {
from: '[email protected]',
baseUrl: 'http://localhost:3000',
templates: {
sendOtp: {
fileName: 'otp.template.hbs',
subject: 'Your verification code',
},
},
},
otp: {
assignment: 'userOtp',
category: 'auth-login',
type: 'numeric',
expiresIn: '10m',
},
},
// Optional: Enable Admin endpoints
// Provide a CRUD adapter + DTOs and import the repository via
// TypeOrmModule.forFeature([...]). Enable by passing `admin` at the
// top-level of RocketsServerModule.forRoot/forRootAsync options.
// See the admin how-to section for a complete example.
}),
}),
],
})
export class AppModule {}Step 4: Create Your Main Application
// main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ExceptionsFilter } from '@concepta/nestjs-common';
import { SwaggerUiService } from '@concepta/nestjs-swagger-ui';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Enable validation
app.useGlobalPipes(new ValidationPipe());
// get the swagger ui service, and set it up
const swaggerUiService = app.get(SwaggerUiService);
swaggerUiService.builder().addBearerAuth();
swaggerUiService.setup(app);
const exceptionsFilter = app.get(HttpAdapterHost);
app.useGlobalFilters(new ExceptionsFilter(exceptionsFilter));
await app.listen(3000);
console.log('Application is running on: http://localhost:3000');
console.log('API Documentation: http://localhost:3000/api');
console.log('Using SQLite in-memory database (data resets on restart)');
}
bootstrap();Your First API
With the basic setup complete, your application now provides these endpoints:
Authentication Endpoints
POST /signup- Register a new userPOST /token/password- Login with username/password (returns 200 OK with tokens)POST /token/refresh- Refresh access tokenPOST /recovery/login- Initiate username recoveryPOST /recovery/password- Initiate password resetPATCH /recovery/password- Reset password with passcodeGET /recovery/passcode/:passcode- Validate recovery passcode
OAuth Endpoints
GET /oauth/authorize- Redirect to OAuth provider (Google, GitHub, Apple)GET /oauth/callback- Handle OAuth callback and return tokensPOST /oauth/callback- Handle OAuth callback via POST method
User Management Endpoints
GET /user- Get current user profilePATCH /user- Update current user profile
Admin Endpoints (optional)
If you enable the admin module (see How-to Guides > admin), these routes become
available and are protected by AdminGuard:
GET /admin/users- List usersGET /admin/users/:id- Get a userPOST /admin/users- Create a userPATCH /admin/users/:id- Update a userPUT /admin/users/:id- Replace a userDELETE /admin/users/:id- Delete a user
OTP Endpoints
POST /otp- Send OTP to user email (returns 200 OK)PATCH /otp- Confirm OTP code (returns 200 OK with tokens)
Testing the Setup
1. Start Your Application
npm run start:dev2. Register a New User
curl -X POST http://localhost:3000/signup \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123",
"username": "testuser"
}'Expected response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"username": "testuser",
"active": true,
"dateCreated": "2024-01-01T00:00:00.000Z",
"dateUpdated": "2024-01-01T00:00:00.000Z",
"dateDeleted": null,
"version": 1
}3. Login and Get Access Token
curl -X POST http://localhost:3000/token/password \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"password": "SecurePass123"
}'Expected response (200 OK):
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Note: The login endpoint returns a 200 OK status (not 201 Created) as it's retrieving tokens, not creating a new resource.
Defaults Working: All authentication endpoints work out-of-the-box with sensible defaults.
4. Access Protected Endpoint
curl -X GET http://localhost:3000/user \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE"Expected response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"username": "testuser",
"active": true,
"dateCreated": "2024-01-01T00:00:00.000Z",
"dateUpdated": "2024-01-01T00:00:00.000Z",
"dateDeleted": null,
"version": 1
}5. Test OTP Functionality
# Send OTP (returns 200 OK)
curl -X POST http://localhost:3000/otp \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]"
}'
# Check console for the "email" that would be sent with the OTP code
# Then confirm with the code (replace 123456 with actual code)
# Returns 200 OK with tokens
curl -X PATCH http://localhost:3000/otp \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"passcode": "123456"
}'Expected OTP confirm response (200 OK):
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}6. Test OAuth Functionality
# Redirect to Google OAuth (returns 200 OK)
curl -X GET "http://localhost:3000/oauth/authorize?provider=google&scopes=email,profile"
# Redirect to GitHub OAuth (returns 200 OK)
curl -X GET "http://localhost:3000/oauth/authorize?provider=github&scopes=user,email"
# Redirect to Apple OAuth (returns 200 OK)
curl -X GET "http://localhost:3000/oauth/authorize?provider=apple&scopes=email,name"
# Handle OAuth callback (returns 200 OK with tokens)
curl -X GET "http://localhost:3000/oauth/callback?provider=google"Expected OAuth callback response (200 OK):
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}🎉 Congratulations! You now have a fully functional authentication system with user management, JWT tokens, OAuth integration, and API documentation running with minimal configuration.
💡 Pro Tip: Since we're using an in-memory database, all data is lost when you restart the application. This is perfect for testing and development!
Troubleshooting
Common Issues
AuthJwtGuard Dependency Error
If you encounter this error:
Nest can't resolve dependencies of the AuthJwtGuard
(AUTHENTICATION_MODULE_SETTINGS_TOKEN, ?). Please make sure that the
argument Reflector at index [1] is available in the AuthJwtModule context.Module Resolution Errors
If you're getting dependency resolution errors:
- NestJS Version: Ensure you're using NestJS
^10.0.0 - Alpha Packages: All
@concepta/*packages should use the same alpha version (e.g.,^7.0.0-alpha.6) - Clean Installation: Try deleting
node_modulesandpackage-lock.json, then runyarn install
Module Resolution Errors (TypeScript)
If TypeScript can't find modules like @concepta/nestjs-typeorm-ext:
yarn add @concepta/nestjs-typeorm-ext @concepta/nestjs-common \
--saveAll dependencies listed in the installation section are required and must be installed explicitly.
How-to Guides
This section provides comprehensive guides for every configuration option
available in the RocketsServerOptionsInterface. Each guide explains what the
option does, how it connects with core modules, when you should customize it
(since defaults are provided), and includes real-world examples.
Configuration Overview
The Rockets SDK uses a hierarchical configuration system with the following structure:
interface RocketsServerOptionsInterface {
settings?: RocketsServerSettingsInterface;
swagger?: SwaggerUiOptionsInterface;
authentication?: AuthenticationOptionsInterface;
jwt?: JwtOptions;
authJwt?: AuthJwtOptionsInterface;
authLocal?: AuthLocalOptionsInterface;
authRecovery?: AuthRecoveryOptionsInterface;
refresh?: AuthRefreshOptions;
authVerify?: AuthVerifyOptionsInterface;
authRouter?: AuthRouterOptionsInterface;
user?: UserOptionsInterface;
password?: PasswordOptionsInterface;
otp?: OtpOptionsInterface;
email?: Partial<EmailOptionsInterface>;
services: {
userModelService?: RocketsServerUserModelServiceInterface;
notificationService?: RocketsServerNotificationServiceInterface;
verifyTokenService?: VerifyTokenService;
issueTokenService?: IssueTokenServiceInterface;
validateTokenService?: ValidateTokenServiceInterface;
validateUserService?: AuthLocalValidateUserServiceInterface;
userPasswordService?: UserPasswordServiceInterface;
userPasswordHistoryService?: UserPasswordHistoryServiceInterface;
userAccessQueryService?: CanAccess;
mailerService: EmailServiceInterface; // Required
};
}settings
What it does: Global settings that configure the custom OTP and email services provided by RocketsServer. These settings are used by the custom OTP controller and notification services, not by the core authentication modules.
Core services it connects to: RocketsServerOtpService, RocketsServerNotificationService
When to update: Required when using the custom OTP endpoints
(POST /otp, PATCH /otp). The defaults use placeholder values that won't
work in real applications.
Real-world example: Setting up email configuration for the custom OTP system:
settings: {
email: {
from: '[email protected]',
baseUrl: 'https://app.mycompany.com',
tokenUrlFormatter: (baseUrl, token) =>
`${baseUrl}/auth/verify?token=${token}&utm_source=email`,
templates: {
sendOtp: {
fileName: 'custom-otp.template.hbs',
subject: 'Your {{appName}} verification code - expires in 10 minutes',
},
},
},
otp: {
assignment: 'userOtp',
category: 'auth-login',
type: 'numeric', // Use 6-digit numeric codes instead of UUIDs
expiresIn: '10m', // Shorter expiry for security
},
}authentication
What it does: Core authentication module configuration that handles token verification, validation services and the payload of the token. It provides three key services:
verifyTokenService: Handles two-step token verification - first cryptographically verifying JWT tokens using JwtVerifyTokenService, then optionally validating the decoded payload through a validateTokenService. Used by authentication guards and protected routes.
issueTokenService: Generates and signs new JWT tokens for authenticated users. Creates both access and refresh tokens with user payload data and builds complete authentication responses. Used during login, signup, and token refresh flows.
validateTokenService: Optional service for custom business logic validation beyond basic JWT verification. Can check user existence, token blacklists, account status, or any other custom validation rules.
Core modules it connects to: AuthenticationModule (the base authentication system)
When to update: When you need to customize core authentication behavior, provide custom token services or change how the token payload is structured. Common scenarios include:
- Implementing custom token verification logic
- Adding business-specific token validation rules
- Modifying token generation and payload structure
- Integrating with external authentication systems
Real-world example: Custom authentication configuration:
authentication: {
settings: {
enableGuards: true, // Default: true
},
// Optional: Custom services (defaults are provided)
issueTokenService: new CustomTokenIssuanceService(),
verifyTokenService: new CustomTokenVerificationService(),
validateTokenService: new CustomTokenValidationService(),
}Note: All token services have working defaults. Only customize if you need specific business logic.
jwt
What it does: JWT token configuration including secrets, expiration times, and token services.
Core modules it connects to: JwtModule, AuthJwtModule, AuthRefreshModule
When to update: Only needed if loading JWT settings from a source other than environment variables (e.g. config files, external services, etc).
Environment Variables: The JWT module automatically uses these environment variables with sensible defaults:
JWT_MODULE_DEFAULT_EXPIRES_IN(default:'1h')JWT_MODULE_ACCESS_EXPIRES_IN(default:'1h')JWT_MODULE_REFRESH_EXPIRES_IN(default:'99y')JWT_MODULE_ACCESS_SECRET(required in production, auto-generated in development, if not provided)JWT_MODULE_REFRESH_SECRET(defaults to access secret if not provided)
Default Behavior:
- Development: JWT secrets are auto-generated if not provided
- Production:
JWT_MODULE_ACCESS_SECRETis required (with NODE_ENV=production) - Token Services: Default
JwtIssueTokenServiceandJwtVerifyTokenServiceare provided - Multiple Token Types: Separate access and refresh token handling
Security Notes:
- Production requires explicit JWT secrets for security
- Development auto-generates secrets for convenience
- Refresh tokens have longer expiration by default
- All token operations are handled automatically
Real-world example: Custom JWT configuration (optional - defaults work for most cases):
jwt: {
settings: {
default: {
signOptions: {
issuer: 'mycompany.com',
audience: 'mycompany-api',
},
},
access: {
signOptions: {
issuer: 'mycompany.com',
audience: 'mycompany-api',
},
},
refresh: {
signOptions: {
issuer: 'mycompany.com',
audience: 'mycompany-refresh',
},
},
},
// Optional: Custom services (defaults are provided)
jwtIssueTokenService: new CustomJwtIssueService(),
jwtVerifyTokenService: new CustomJwtVerifyService(),
}Note: Environment variables are automatically used for secrets and
expiration times. Only customize jwt.settings if you need specific JWT
options like issuer/audience, you can also use the environment variables to
configure the JWT module.
authJwt
What it does: JWT-based authentication strategy configuration, including how tokens are extracted from requests.
Core modules it connects to: AuthJwtModule, provides JWT authentication guards and strategies
When to update: When you need custom token extraction logic or want to modify JWT authentication behavior.
Real-world example: Custom token extraction for mobile apps that send tokens in custom headers:
authJwt: {
settings: {
jwtFromRequest: ExtractJwt.fromExtractors([
ExtractJwt.fromAuthHeaderAsBearerToken(), // Standard Bearer token
ExtractJwt.fromHeader('x-api-token'), // Custom header for mobile
(request) => {
// Custom extraction from cookies for web apps
return request.cookies?.access_token;
},
]),
},
// Optional settings (defaults are sensible)
appGuard: true, // Default: true - set true to apply JWT guard globally
// Optional services (defaults are provided)
verifyTokenService: new CustomJwtVerifyService(),
userModelService: new CustomUserLookupService(),
}Note: Default token extraction uses standard Bearer token from Authorization header. Only customize if you need alternative token sources.
authLocal
What it does: Local authentication (username/password) configuration and validation services.
Core modules it connects to: AuthLocalModule, handles login endpoint and credential validation
When to update: When you need custom password validation, user lookup logic, or want to integrate with external authentication systems.
Real-world example: Custom local authentication with email login:
authLocal: {
settings: {
usernameField: 'email', // Default: 'username'
passwordField: 'password', // Default: 'password'
},
// Optional services (defaults work with TypeORM entities)
validateUserService: new CustomUserValidationService(),
userModelService: new CustomUserModelService(),
issueTokenService: new CustomTokenIssuanceService(),
}Environment Variables:
AUTH_LOCAL_USERNAME_FIELD- defaults to'username'AUTH_LOCAL_PASSWORD_FIELD- defaults to'password'
Note: The default services work automatically with your TypeORM User entity. Only customize if you need specific validation logic.
authRecovery
What it does: Password recovery and account recovery functionality including email notifications and OTP generation.
Core modules it connects to: AuthRecoveryModule, provides password reset endpoints
When to update: When you need custom recovery flows, different notification methods, or integration with external services.
Real-world example: Multi-channel recovery system with SMS and email options:
authRecovery: {
settings: {
tokenExpiresIn: '1h', // Recovery token expiration
maxAttempts: 3, // Maximum recovery attempts
},
emailService: new CustomEmailService(),
otpService: new CustomOtpService(),
userModelService: new CustomUserModelService(),
userPasswordService: new CustomPasswordService(),
notificationService: new MultiChannelNotificationService(), // SMS + Email
}refresh
What it does: Refresh token configuration for maintaining user sessions without requiring re-authentication.
Core modules it connects to: AuthRefreshModule, provides token refresh endpoints
When to update: When you need custom refresh token behavior, different expiration strategies, or want to implement token rotation.
Real-world example: Secure refresh token rotation for high-security applications:
refresh: {
settings: {
jwtFromRequest: ExtractJwt.fromBodyField('refreshToken'),
tokenRotation: true, // Issue new refresh token on each use
revokeOnUse: true, // Revoke old refresh token
},
verifyTokenService: new SecureRefreshTokenVerifyService(),
issueTokenService: new RotatingTokenIssueService(),
userModelService: new AuditableUserModelService(), // Log refresh attempts
}authVerify
What it does: Email verification and account verification functionality.
Core modules it connects to: AuthVerifyModule, provides email verification endpoints
When to update: When you need custom verification flows, different verification methods, or want to integrate with external verification services.
Real-world example: Multi-step verification with phone and email:
authVerify: {
settings: {
verificationRequired: true, // Require verification before login
verificationExpiresIn: '24h',
},
emailService: new CustomEmailService(),
otpService: new CustomOtpService(),
userModelService: new CustomUserModelService(),
notificationService: new MultiStepVerificationService(), // Email + SMS
}authRouter
What it does: OAuth router configuration that handles routing to different OAuth providers (Google, GitHub, Apple) based on the provider parameter in the request.
Core modules it connects to: AuthRouterModule, provides OAuth routing and guards
When to update: When you need to add or remove OAuth providers, customize OAuth guard behavior, or modify OAuth routing logic.
Real-world example: Custom OAuth configuration with multiple providers:
authRouter: {
guards: [
{ name: 'google', guard: AuthGoogleGuard },
{ name: 'github', guard: AuthGithubGuard },
{ name: 'apple', guard: AuthAppleGuard },
// Add custom OAuth providers
{ name: 'custom', guard: CustomOAuthGuard },
],
settings: {
// Custom OAuth router settings
defaultProvider: 'google',
enableProviderValidation: true,
},
}Default Configuration: The SDK automatically configures Google, GitHub, and Apple OAuth providers with sensible defaults.
OAuth Flow:
- Client calls
/oauth/authorize?provider=google&scopes=email profile - AuthRouterGuard routes to the appropriate OAuth guard based on provider
- OAuth guard redirects to the provider's authorization URL
- User authenticates with the OAuth provider
- Provider redirects back to
/oauth/callback?provider=google - AuthRouterGuard processes the callback and returns JWT tokens
user
What it does: User management configuration including CRUD operations, password management, and access control.
Core modules it connects to: UserModule, provides user management endpoints
When to update: When you need custom user management logic, different access control, or want to integrate with external user systems.
Real-world example: Enterprise user management with role-based access control:
user: {
imports: [
TypeOrmExtModule.forFeature({
user: { entity: UserEntity },
userProfile: { entity: UserProfileEntity },
userPasswordHistory: { entity: UserPasswordHistoryEntity },
}),
],
settings: {
enableProfiles: true, // Enable user profiles
enablePasswordHistory: true, // Track password history
},
userModelService: new EnterpriseUserModelService(),
userPasswordService: new SecurePasswordService(),
userAccessQueryService: new RoleBasedAccessService(),
userPasswordHistoryService: new PasswordHistoryService(),
}password
What it does: Password policy and validation configuration.
Core modules it connects to: PasswordModule, provides password validation across the system
When to update: When you need to enforce specific password policies or integrate with external password validation services.
Real-world example: Enterprise password policy with complexity requirements:
password: {
settings: {
minPasswordStrength: 3, // 0-4 scale (default: 2)
maxPasswordAttempts: 5, // Default: 3
requireCurrentToUpdate: true, // Default: false
passwordHistory: 12, // Remember last 12 passwords
},
}Environment Variables:
PASSWORD_MIN_PASSWORD_STRENGTH- defaults to4if production,0if development (0-4 scale)PASSWORD_MAX_PASSWORD_ATTEMPTS- defaults to3PASSWORD_REQUIRE_CURRENT_TO_UPDATE- defaults tofalse
Note: Password strength is automatically calculated using zxcvbn. History tracking is optional and requires additional configuration.
otp
What it does: One-time password configuration for the OTP system.
Core modules it connects to: OtpModule, provides OTP generation and validation
When to update: When you need custom OTP behavior, different OTP types, or want to integrate with external OTP services.
Interface: OtpSettingsInterface from @concepta/nestjs-otp
interface OtpSettingsInterface {
types: Record<string, OtpTypeServiceInterface>;
clearOnCreate: boolean;
keepHistoryDays?: number;
rateSeconds?: number;
rateThreshold?: number;
}Environment Variables:
OTP_CLEAR_ON_CREATE- defaults tofalseOTP_KEEP_HISTORY_DAYS- no default (optional)OTP_RATE_SECONDS- no default (optional)OTP_RATE_THRESHOLD- no default (optional)
Real-world example: High-security OTP configuration with rate limiting:
otp: {
imports: [
TypeOrmExtModule.forFeature({
userOtp: { entity: UserOtpEntity },
}),
],
settings: {
types: {
uuid: {
generator: () => require('uuid').v4(),
validator: (value: string, expected: string) => value === expected,
},
},
clearOnCreate: true, // Clear old OTPs when creating new ones
keepHistoryDays: 30, // Keep OTP history for 30 days
rateSeconds: 60, // Minimum 60 seconds between OTP requests
rateThreshold: 5, // Maximum 5 attempts within rate window
},
}What it does: Email service configuration for sending notifications and templates.
Core modules it connects to: EmailModule, used by AuthRecoveryModule and AuthVerifyModule
When to update: When you need to use a different email service provider or customize email sending behavior.
Interface: EmailServiceInterface from @concepta/nestjs-email
Configuration example:
email: {
service: new YourCustomEmailService(), // Must implement EmailServiceInterface
settings: {}, // Settings object is empty
}services
The services object contains injectable services that customize core
functionality. Each service has specific responsibilities:
services.userModelService
What it does: Core user lookup service used across multiple authentication modules.
Core modules it connects to: AuthJwtModule, AuthRefreshModule, AuthLocalModule, AuthRecoveryModule
When to update: When you need to integrate with external user systems or implement custom user lookup logic.
Interface: UserModelServiceInterface from @concepta/nestjs-user
Configuration example:
services: {
userModelService: new YourCustomUserModelService(), // Must implement UserModelServiceInterface
}services.notificationService
What it does: Handles sending notifications for recovery and verification processes.
Core modules it connects to: AuthRecoveryModule, AuthVerifyModule
When to update: When you need custom notification channels (SMS, push notifications) or integration with external notification services.
Interface: NotificationServiceInterface from @concepta/nestjs-authentication
Configuration example:
services: {
notificationService: new YourCustomNotificationService(), // Must implement NotificationServiceInterface
}services.verifyTokenService
What it does: Verifies JWT tokens for authentication.
Core modules it connects to: AuthenticationModule, JwtModule
When to update: When you need custom token verification logic or integration with external token validation services.
Interface: VerifyTokenServiceInterface from @concepta/nestjs-authentication
Configuration example:
services: {
verifyTokenService: new YourCustomVerifyTokenService(), // Must implement VerifyTokenServiceInterface
}services.issueTokenService
What it does: Issues JWT tokens for authenticated users.
Core modules it connects to: AuthenticationModule, AuthLocalModule, AuthRefreshModule
When to update: When you need custom token issuance logic or want to include additional claims.
Interface: IssueTokenServiceInterface from @concepta/nestjs-authentication
Configuration example:
services: {
issueTokenService: new YourCustomIssueTokenService(), // Must implement IssueTokenServiceInterface
}services.validateTokenService
What it does: Validates token structure and claims.
Core modules it connects to: AuthenticationModule
When to update: When you need custom token validation rules or security checks.
Interface: ValidateTokenServiceInterface from @concepta/nestjs-authentication
Configuration example:
services: {
validateTokenService: new YourCustomValidateTokenService(), // Must implement ValidateTokenServiceInterface
}services.validateUserService
What it does: Validates user credentials during local authentication.
Core modules it connects to: AuthLocalModule
When to update: When you need custom credential validation or integration with external authentication systems.
Interface: ValidateUserServiceInterface from @concepta/nestjs-authentication
Configuration example:
services: {
validateUserService: new YourCustomValidateUserService(), // Must implement ValidateUserServiceInterface
}services.userPasswordService
What it does: Handles password operations including hashing and validation.
Core modules it connects to: UserModule, AuthRecoveryModule
When to update: When you need custom password hashing algorithms or password policy enforcement.
Interface: UserPasswordServiceInterface from @concepta/nestjs-user
Configuration example:
services: {
userPasswordService: new YourCustomUserPasswordService(), // Must implement UserPasswordServiceInterface
}services.userPasswordHistoryService
What it does: Manages password history to prevent password reuse.
Core modules it connects to: UserModule
When to update: When you need to enforce password history policies or custom password tracking.
Interface: UserPasswordHistoryServiceInterface from @concepta/nestjs-user
Configuration example:
services: {
userPasswordHistoryService: new YourCustomPasswordHistoryService(), // Must implement UserPasswordHistoryServiceInterface
}services.userAccessQueryService
What it does: Handles access control and permission queries.
Core modules it connects to: UserModule
When to update: When you need custom access control logic or integration with external authorization systems.
Interface: CanAccess from @concepta/nestjs-common
Configuration example:
services: {
userAccessQueryService: new YourCustomAccessQueryService(), // Must implement CanAccess
}services.mailerService (Required)
What it does: Core email sending service used throughout the system.
Core modules it connects to: EmailModule, AuthRecoveryModule, AuthVerifyModule, OTP system
When to update: Always required. You must provide a working email service for production.
Interface: EmailServiceInterface from @concepta/nestjs-email
Configuration example:
services: {
mailerService: new YourCustomMailerService(), // Must implement EmailServiceInterface
}crud
Add a new CRUD endpoint for any entity using @concepta/nestjs-crud with
minimal boilerplate. This section provides step-by-step instructions for AI
agents to implement CRUD operations following the v7.0.0-alpha.6 patterns.
IMPORTANT FOR AI AGENTS: Follow this exact pattern when implementing
CRUD functionality. The pattern uses ConfigurableCrudBuilder plus a
TypeOrmCrudAdapter and requires specific imports and structure.
Required Imports for CRUD Implementation
Always import these modules for CRUD:
import { CrudModule } from '@concepta/nestjs-crud'; // For CrudModule.forRoot()
import { TypeOrmModule } from '@nestjs/typeorm'; // For TypeOrmModule.forFeature()
import { TypeOrmCrudAdapter } from '@concepta/nestjs-crud'; // For the adapter patternDO NOT use TypeOrmExtModule for CRUD - this is only for model services. Use standard TypeOrmModule instead.
Module Import Requirements
Required in your module:
@Module({
imports: [
CrudModule.forRoot({}), // Required for CRUD functionality
TypeOrmModule.forFeature([ProjectEntity]), // Required for repository injection
// NOT TypeOrmExtModule - that's only for model services
],
// ... rest of module
})Complete CRUD Implementation Pattern
1) Define your Entity
// entities/project.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity('project')
export class ProjectEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
@Column()
name!: string;
@Column({ nullable: true })
description?: string;
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
createdAt!: Date;
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', onUpdate: 'CURRENT_TIMESTAMP' })
updatedAt!: Date;
}2) Define your DTOs
// dto/project/project.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class ProjectDto {
@ApiProperty()
id!: string;
@ApiProperty()
name!: string;
@ApiProperty({ required: false })
description?: string;
@ApiProperty()
createdAt!: Date;
@ApiProperty()
updatedAt!: Date;
}
// dto/project/project-create.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
export class ProjectCreateDto {
@ApiProperty()
@IsString()
@IsNotEmpty()
name!: string;
@ApiProperty({ required: false })
@IsString()
@IsOptional()
description?: string;
}
// dto/project/project-update.dto.ts
import { PartialType } from '@nestjs/swagger';
import { ProjectCreateDto } from './project-create.dto';
export class ProjectUpdateDto extends PartialType(ProjectCreateDto) {}
// dto/project/project-paginated.dto.ts
import { CrudResponsePaginatedDto } from '@concepta/nestjs-crud';
import { ProjectDto } from './project.dto';
export class ProjectPaginatedDto extends CrudResponsePaginatedDto(ProjectDto) {}3) Create a TypeOrmCrudAdapter (REQUIRED PATTERN)
AI AGENTS: This is the correct adapter pattern for v7.0.0-alpha.6:
// adapters/project-typeorm-crud.adapter.ts
import { Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmCrudAdapter } from '@concepta/nestjs-crud';
import { ProjectEntity } from '../entities/project.entity';
/**
* Project CRUD Adapter using TypeORM
*
* PATTERN NOTE: This follows the standard pattern where:
* - Extends TypeOrmCrudAdapter<EntityType>
* - Injects Repository<EntityType> via @InjectRepository
* - Calls super(repo) to initialize the adapter
*/
@Injectable()
export class ProjectTypeOrmCrudAdapter extends TypeOrmCrudAdapter<ProjectEntity> {
constructor(
@InjectRepository(ProjectEntity)
repo: Repository<ProjectEntity>,
) {
super(repo);
}
}4) Create a CRUD Builder with build() Method
// crud/project-crud.builder.ts
import { ApiTags } from '@nestjs/swagger';
import { ConfigurableCrudBuilder } from '@concepta/nestjs-crud';
import { ProjectEntity } from '../entities/project.entity';
import { ProjectDto } from '../dto/project/project.dto';
import { ProjectCreateDto } from '../dto/project/project-create.dto';
import { ProjectUpdateDto } from '../dto/project/project-update.dto';
import { ProjectPaginatedDto } from '../dto/project/project-paginated.dto';
import { ProjectTypeOrmCrudAdapter } from '../adapters/project-typeorm-crud.adapter';
export const PROJECT_CRUD_SERVICE_TOKEN = Symbol('PROJECT_CRUD_SERVICE_TOKEN');
export class ProjectCrudBuilder extends ConfigurableCrudBuilder<
ProjectEntity,
ProjectCreateDto,
ProjectUpdateDto
> {
constructor() {
super({
service: {
injectionToken: PROJECT_CRUD_SERVICE_TOKEN,
adapter: ProjectTypeOrmCrudAdapter,
},
controller: {
path: 'projects',
model: {
type: ProjectDto,
paginatedType: ProjectPaginatedDto,
},
extraDecorators: [ApiTags('projects')],
},
getMany: {},
getOne: {},
createOne: { dto: ProjectCreateDto },
updateOne: { dto: ProjectUpdateDto },
replaceOne: { dto: ProjectUpdateDto },
deleteOne: {},
});
}
}5) Use build() Method to Get ConfigurableClasses
AI AGENTS: You must call .build() and extract the classes:
// crud/project-crud.builder.ts (continued)
// Call build() to get the configurable classes
const {
ConfigurableServiceClass,
ConfigurableControllerClass,
} = new ProjectCrudBuilder().build();
// Export the classes that extend the configurable classes
export class ProjectCrudService extends ConfigurableServiceClass {
// Inherits all CRUD operations: getMany, getOne, createOne, updateOne, replaceOne, deleteOne
}
export class ProjectController extends ConfigurableControllerClass {
// Inherits all CRUD endpoints:
// GET /projects (getMany)
// GET /projects/:id (getOne)
// POST /projects (createOne)
// PATCH /projects/:id (updateOne)
// PUT /projects/:id (replaceOne)
// DELETE /projects/:id (deleteOne)
}
6) Register in a Module (COMPLETE PATTERN)
AI AGENTS: This is the exact module pattern you must follow:
// modules/project.module.ts
import { Module } from '@nestjs/common';
import { CrudModule } from '@concepta/nestjs-crud'; // REQUIRED
import { TypeOrmModule } from '@nestjs/typeorm'; // REQUIRED (NOT TypeOrmExtModule)
import { ProjectEntity } from '../entities/project.entity';
import { ProjectTypeOrmCrudAdapter } from '../adapters/project-typeorm-crud.adapter';
import { ProjectController, ProjectServiceProvider } from '../crud/project-crud.builder';
@Module({
imports: [
CrudModule.forRoot({}), // REQUIRED for CRUD functionality
TypeOrmModule.forFeature([ProjectEntity]), // REQUIRED for repository injection
],
providers: [
ProjectTypeOrmCrudAdapter, // The adapter with @Injectable
ProjectServiceProvider, // From the builder.build() result
],
controllers: [
ProjectController, // From the builder.build() result
],
})
export class ProjectModule {}7) Wire up in Main App Module
// app.module.ts (add to imports)
@Module({
imports: [
// ... other imports
ProjectModule, // Your new CRUD module
],
})
export class AppModule {}Key Patterns for AI Agents
1. Adapter Pattern: Always create a EntityTypeOrmCrudAdapter that extends
TypeOrmCrudAdapter<Entity> (or any other adapter you may need) and injects
Repository<Entity>.
2. Builder Pattern: Use ConfigurableCrudBuilder and call .build() to
get ConfigurableServiceClass and ConfigurableControllerClass.
3. Module Imports: Always use:
CrudModule.forRoot({})- for CRUD functionalityTypeOrmModule.forFeature([Entity])- for repository injection- NOT
TypeOrmExtModule- that's only for model services
4. Service Token: Create a unique Symbol for each CRUD service token.
5. DTOs: Always create separate DTOs for Create, Update, Response, and Paginated types.
Generated Endpoints
The CRUD builder automatically generates these RESTful endpoints:
GET /projects- List projects with pagination and filteringGET /projects/:id- Get a single project by IDPOST /projects- Create a new projectPATCH /projects/:id- Partially update a projectPUT /projects/:id- Replace a project completelyDELETE /projects/:id- Delete a project
Swagger Documentation
All endpoints are automatically documented in Swagger with:
- Request/response schemas based on your DTOs
- API tags specified in
extraDecorators - Validation rules from class-validator decorators
- Pagination parameters for list endpoints
This pattern provides a complete, production-ready CRUD API with minimal boilerplate code while maintaining full type safety and comprehensive documentation.
Explanation
Architecture Overview
The Rockets SDK follows a modular, layered architecture designed for enterprise applications:
graph TB
subgraph AL["Application Layer"]
direction BT
A[Controllers]
B[DTOs]
C[Swagger Docs]
end
subgraph SL["Service Layer"]
direction BT
D[Auth Services]
E[User Services]
F[OTP Services]
end
subgraph IL["Integration Layer"]
direction BT
G[JWT Module]
H[Email Module]
I[Password Module]
end
subgraph DL["Data Layer"]
direction BT
J[TypeORM Integration]
L[Custom Adapters]
end
AL --> SL
SL --> IL
IL --> DLCore Components
- RocketsServerModule: The main module that orchestrates all other modules
- Authentication Layer: Handles JWT, local auth, refresh tokens
- User Management: CRUD operations, profiles, password management
- OTP System: One-time password generation and validation
- Email Service: Template-based email notifications
- Data Layer: TypeORM integration with adapter support
Design Decisions
1. Unified Module Approach
Decision: Combine multiple authentication modules into a single package.
Rationale:
- Reduces setup complexity for developers
- Ensures compatibility between modules
- Provides a consistent configuration interface
- Eliminates version conflicts between related packages
Trade-offs:
- Larger bundle size if only some features are needed
- Less granular control over individual module versions
2. Configuration-First Design
Decision: Use extensive configuration objects rather than code-based setup.
Rationale:
- Enables environment-specific configurations
- Supports async configuration with dependency injection
- Makes the system more declarative and predictable
- Facilitates testing with different configurations
Example:
// Configuration-driven approach
RocketsServerModule.forRoot({
jwt: { settings: { /* ... */ } },
user: { /* ... */ },
otp: { /* ... */ },
});
// vs. imperative approach (not used)
const jwtModule = new JwtModule(jwtConfig);
const userModule = new UserModule(userConfig);
// ... manual wiring3. Adapter Pattern for Data Access
Decision: Use repository adapters instead of direct TypeORM coupling.
Rationale:
- Supports multiple database types and ORMs
- Enables custom data sources (APIs, NoSQL, etc.)
- Facilitates testing with mock repositories
- Provides flexibility for future data layer changes
Implementation: Uses the adapter pattern with a standardized repository interface to support multiple database types and ORMs.
4. Service Injection Pattern
Decision: Allow custom service implementations through dependency injection.
Rationale:
- Enables integration with existing systems
- Supports custom business logic
- Facilitates testing with mock services
- Maintains loose coupling between components
Example:
services: {
mailerService: new CustomMailerService(),
userModelService: new CustomUserModelService(),
notificationService: new CustomNotificationService(),
}5. Global vs Local Registration
Decision: Support both global and local module registration.
Rationale:
- Global registration simplifies common use cases
- Local registration provides fine-grained control
- Supports micro-service architectures
- Enables gradual adoption in existing applications
Core Concepts
1. Testing Support
The Rockets SDK provides comprehensive testing support including:
Unit Tests: Individual module and service testing with mock dependencies Integration Tests: End-to-end testing of complete authentication flows E2E Tests: Full application testing with real HTTP requests
Example E2E Test Structure:
// auth-oauth.controller.e2e-spec.ts
describe('AuthOAuthController (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
TypeOrmExtModule.forRootAsync({
useFactory: () => ormConfig,
}),
RocketsServerModule.forRoot({
user: {
imports: [
TypeOrmExtModule.forFeature({
user: { entity: UserFixture },
}),
],
},
otp: {
imports: [
TypeOrmExtModule.forFeature({
userOtp: { entity: UserOtpEntityFixture },
}),
],
},
federated: {
imports: [
TypeOrmExtModule.forFeature({
federated: { entity: FederatedEntityFixture },
}),
],
},
services: {
mailerService: mockEmailService,
},
}),
],
controllers: [AuthOAuthController],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(new ValidationPipe());
await app.init();
});
afterAll(async () => {
await app.close();
});
describe('GET /oauth/authorize', () => {
it('should handle authorize with google provider', async () => {
await request(app.getHttpServer())
.get('/oauth/authorize?provider=google&scopes=email profile')
.expect(200);
});
});
describe('GET /oauth/callback', () => {
it('should handle callback with google provider and return tokens', async () => {
const response = await request(app.getHttpServer())
.get('/oauth/callback?provider=google')
.expect(200);
expect(mockIssueTokenService.responsePayload).toHaveBeenCalledWith('test-user-id');
expect(response.body).toEqual({
accessToken: 'mock-access-token',
refreshToken: 'mock-refresh-token',
});
});
});
});Key Testing Features:
- Fixture Support: Pre-built test entities and services
- Mock Services: Easy mocking of email, OTP, and authentication services
- Database Testing: In-memory database support for isolated tests
- Guard Testing: Comprehensive testing of authentication guards
- Error Scenarios: Testing of error conditions and edge cases
2. Authentication Flow
The Rockets SDK implements a comprehensive authentication flow:
1a. User Registration Flow
sequenceDiagram
participant C as Client
participant CT as AuthSignupController
participant PS as PasswordStorageService
participant US as UserModelService
participant D as Database
C->>CT: POST /signup (email, username, password)
CT->>PS: hashPassword(plainPassword)
PS-->>CT: hashedPassword
CT->>US: createUser(userData)
US->>D: Save User Entity
D-->>US: User Created
US-->>CT: User Profile
CT-->>C: 201 Created (User Profile)Services to customize for registration:
PasswordStorageService- Custom password hashing algorithmsUserModelService- Custom user creation logic, validation, external systems integration
1b. User Authentication Flow
sequenceDiagram
participant C as Client
participant G as AuthLocalGuard
participant ST as AuthLocalStrategy
participant VS as AuthLocalValidateUserService
participant US as UserModelService
participant PV as PasswordValidationService
participant D as Database
C->>G: POST /token/password (username, password)
G->>ST: Redirect to Strategy
ST->>ST: Validate DTO Fields
ST->>VS: validateUser(username, password)
VS->>US: byUsername(username)
US->>D: Find User by Username
D-->>US: User Entity
US-->>VS: User Found
VS->>VS: isActive(user)
VS->>PV: validate(user, password)
PV-->>VS: Password Valid
VS-->>ST: Validated User
ST-->>G: Return User
G-->>C: User Added to Request (@AuthUser)Services to customize for authentication:
AuthLocalValidateUserService- Custom credential validation logicUserModelService- Custom user lookup by username, email, or other fieldsPasswordValidationService- Custom password verification algorithms
1c. Token Generation Flow
sequenceDiagram
participant G as AuthLocalGuard
participant CT as AuthPasswordController
participant ITS as IssueTokenService
participant JS as JwtService
participant C as Client
G->>CT: Request with Validated User (@AuthUser)
CT->>ITS: responsePayload(user.id)
ITS->>JS: signAsync(payload) - Access Token
JS-->>ITS: Access Token
ITS->>JS: signAsync(payload, {expiresIn: '7d'}) - Refresh Token
JS-->>ITS: Refresh Token
ITS-->>CT: {accessToken, refreshToken}
CT-->>C: 200 OK (JWT Tokens)Services to customize for token generation:
IssueTokenService- Custom JWT payload, token expiration, additional claimsJwtService- Custom signing algorithms, token structure
1d. Protected Route Access Flow
sequenceDiagram
participant C as Client
participant G as AuthJwtGuard
participant ST as AuthJwtStrategy
participant VTS as VerifyTokenService
participant US as UserModelService
participant D as Database
participant CT as Controller
C->>G: GET /user (Authorization: Bearer token)
G->>ST: Redirect to JWT Strategy
ST->>VTS: verifyToken(accessToken)
VTS-->>ST: Token Valid & Payload
ST->>US: bySubject(payload.sub)
US->>D: Find User by Subject/ID
D-->>US: User Entity
US-->>ST: User Found
ST-->>G: Return User
G->>CT: Add User to Request (@AuthUser)
CT->>D: Get Additional User Data (if needed)
D-->>CT: User Data
CT-->>C: 200 OK (Protected Resource)Services to customize for protected routes:
VerifyTokenService- Custom token verification logic, blacklist checkingUserModelService- Custom user lookup by subject/ID, user status validation
2. OTP Verification Flow
sequenceDiagram
participant C as Client
participant S as Server
participant OS as OTP Service
participant D as Database
participant E as Email Service
Note over C,E: OTP Generation Flow
C->>S: POST /otp (email)
S->>OS: Generate OTP (RocketsServerOtpService)
OS->>D: Store OTP with Expiry
OS->>E: Send Email (NotificationService)
E-->>OS: Email Sent
S-->>C: 201 Created (OTP Sent)
Note over C,E: OTP Verification Flow
C->>S: PATCH /otp (email + passcode)
S->>OS: Validate OTP Code
OS->>D: Check OTP & Mark Used
OS->>S: OTP Valid
S->>S: Generate JWT Tokens (AuthLocalIssueTokenService)
S-->>C: 200 OK (JWT Tokens)3. Token Refresh Flow
sequenceDiagram
participant C as Client
participant G as AuthRefreshGuard
participant ST as AuthRefreshStrategy
participant VTS as VerifyTokenService
participant US as UserModelService
participant D as Database
participant CT as RefreshController
participant ITS as IssueTokenService
Note over C,D: Token Refresh Request
C->>G: POST /token/refresh (refreshToken in body)
G->>ST: Redirect to Refresh Strategy
ST->>VTS: verifyRefreshToken(refreshToken)
VTS-->>ST: Token Valid & Payload
ST->>US: bySubject(payload.sub)
US->>D: Find User by Subject/ID
D-->>US: User Entity
US-->>ST: User Found & Active
ST-->>G: Return User
G->>CT: Add User to Request (@AuthUser)
CT->>ITS: responsePayload(user.id)
ITS-->>CT: New {accessToken, refreshToken}
CT-->>C: 200 OK (New JWT Tokens)Services to customize for token refresh:
VerifyTokenService- Custom refresh token verification, token rotation logicUserModelService- Custom user validation, account status checkingIssueTokenService- Custom new token generation, token rotation policies
4. Password Recovery Flow
4a. Recovery Request Flow
sequenceDiagram
participant C as Client
participant CT as RecoveryController
participant RS as AuthRecoveryService
participant US as UserModelService
participant OS as OtpService
participant NS as NotificationService
participant ES as EmailService
participant D as Database
C->>CT: POST /recovery/password (email)
CT->>RS: recoverPassword(email)
RS->>US: byEmail(email)
US->>D: Find User by Email
D-->>US: User Found (or null)
US-->>RS: User Entity
RS->>OS: create(otpConfig)
OS->>D: Store OTP with Expiry
D-->>OS: OTP Created
OS-->>RS: OTP with Passcode
RS->>NS: sendRecoverPasswordEmail(email, passcode, expiry)
NS->>ES: sendMail(emailOptions)
ES-->>NS: Email Sent
RS-->>CT: Recovery Complete
CT-->>C: 200 OK (Always success for security)Services to customize for recovery request:
UserModelService- Custom user lookup by emailOtpService- Custom OTP generation, expiry logicNotificationService- Custom email templates, delivery methodsEmailService- Custom email providers, formatting
4b. Passcode Validation Flow
sequenceDiagram
participant C as Client
participant CT as RecoveryController
participant RS as AuthRecoveryService
participant OS as OtpService
participant D as Database
C->>CT: GET /recovery/passcode/:passcode
CT->>RS: validatePasscode(passcode)
RS->>OS: validate(assignment, {category, passcode})
OS->>D: Find & Validate OTP
D-->>OS: OTP Valid & User ID
OS-->>RS: Assignee Relation (or null)
RS-->>CT: OTP Valid (or null)
CT-->>C: 200 OK (Valid) / 404 (Invalid)Services to customize for passcode validation:
OtpService- Custom OTP validation, rate limiting
4c. Password Update Flow
sequenceDiagram
participant C as Client
participant CT as RecoveryController
participant RS as AuthRecoveryService
participant OS as OtpService
participant US as UserModelService
participant PS as UserPasswordService
participant NS as NotificationService
participant D as Database
C->>CT: PATCH /recovery/password (passcode, newPassword)
CT->>RS: updatePassword(passcode, newPassword)
RS->>OS: validate(passcode, false)
OS->>D: Validate OTP
D-->>OS: OTP Valid & User ID
OS-->>RS: Assignee Relation
RS->>US: byId(assigneeId)
US->>D: Find User by ID
D-->>US: User Entity
US-->>RS: User Found
RS->>PS: setPassword(newPassword, userId)
PS->>D: Update User Password
D-->>PS: Password Updated
RS->>NS: sendPasswordUpdatedSuccessfullyEmail(email)
RS->>OS: clear(assignment, {category, assigneeId})
OS->>D: Revoke All User Recovery OTPs
RS-->>CT: User Entity (or null)
CT-->>C: 200 OK (Success) / 400 (Invalid OTP)Services to customize for password update:
OtpService- Custom OTP validation and cleanupUserModelService- Custom user lookup validationUserPasswordService- Custom password hashing, policiesNotificationService- Custom success notifications
5. OAuth Flow
The Rockets SDK implements a comprehensive OAuth flow for third-party authentication:
5a. OAuth Authorization Flow
sequenceDiagram
participant C as Client
participant AR as AuthRouterGuard
participant AG as AuthGoogleGuard
participant G as Google OAuth
participant C as Client
C->>AR: GET /oauth/authorize?provider=google&scopes=email profile
AR->>AR: Route to AuthGoogleGuard
AR->>AG: canActivate(context)
AG->>G: Redirect to Google OAuth URL
G-->>C: Google Login Page
C->>G: User Authenticates
G->>C: Redirect to /oauth/callback?code=xyzServices to customize for OAuth:
AuthRouterGuard- Custom OAuth routing logic, provider validationAuthGoogleGuard/AuthGithubGuard/AuthAppleGuard- Custom OAuth provider integrationFederatedModule- Custom user creation/lookup from OAuth dataUserModelService- Custom user creation and lookup logicIssueTokenService- Custom token generation for OAuth users
userCrud
User CRUD management is now provided via a dynamic submodule that you enable through the module extras. It provides comprehensive user management including:
- User signup endpoints (
POST /signup) - User profile management (
GET /user,PATCH /user) - Admin user CRUD operations (
/admin/users/*)
All endpoints are properly guarded and documented in Swagger.
Prerequisites
- A TypeORM repository for your user entity available via
TypeOrmModule.forFeature([UserEntity]) - A CRUD adapter implementing
CrudAdapter(e.g., aTypeOrmCrudAdapter) - DTOs for model, create, update (optional replace/many)
Minimal adapter example
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TypeOrmCrudAdapter } from '@concepta/nestjs-crud';
import { UserEntity } from './entities/user.entity';
@Injectable()
export class AdminUserTypeOrmCrudAdapter extends TypeOrmCrudAdapter<UserEntity> {
constructor(
@InjectRepository(UserEntity) repo: Repository<UserEntity>,
) {
super(repo);
}
}Enable userCrud in RocketsServerModule
@Module({
imports: [
TypeOrmModule.forFeature([UserEntity]),
RocketsServerModule.forRootAsync({
// ... other options
imports: [TypeOrmModule.forFeature([UserEntity])],
useFactory: () => ({
services: {
mai