@nodelabs/nest-aws-cognito
v0.0.1
Published
NestJS module for AWS Cognito (authentication & user management)
Downloads
42
Readme
@nodelabs/nest-aws-cognito
A NestJS dynamic module for AWS Cognito — user authentication, registration, admin user management, password flows, group assignment, and email template customisation. Supports both static (forRoot) and async (forRootAsync) configuration, with optional global registration.
Table of Contents
- Installation
- Quick Start
- Configuration
- AWS Cognito Setup Requirements
- Available Services
- API Reference
- Exports
Installation
npm install @nodelabs/nest-aws-cognito @aws-sdk/client-cognito-identity-providerPeer Dependencies
npm install @nestjs/common @nestjs/config reflect-metadata rxjsQuick Start
// app.module.ts
import { Module } from '@nestjs/common';
import { CognitoModule } from '@nodelabs/nest-aws-cognito';
@Module({
imports: [
CognitoModule.forRoot({
region: 'us-east-1',
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
clientId: 'YOUR_COGNITO_APP_CLIENT_ID',
clientSecret: 'YOUR_COGNITO_APP_CLIENT_SECRET',
userPoolId: 'us-east-1_XXXXXXXXX',
appName: 'My App',
}),
],
})
export class AppModule {}Configuration
forRoot (static)
CognitoModule.forRoot({
region: 'us-east-1',
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
clientId: 'YOUR_COGNITO_APP_CLIENT_ID',
clientSecret: 'YOUR_COGNITO_APP_CLIENT_SECRET',
userPoolId: 'us-east-1_XXXXXXXXX',
appName: 'My App', // optional — used in default email subjects
isGlobal: true, // optional
})forRootAsync (factory)
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CognitoModule } from '@nodelabs/nest-aws-cognito';
@Module({
imports: [
ConfigModule.forRoot(),
CognitoModule.forRootAsync({
isGlobal: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
region: config.get<string>('AWS_REGION'),
accessKeyId: config.get<string>('AWS_ACCESS_KEY_ID'),
secretAccessKey: config.get<string>('AWS_SECRET_ACCESS_KEY'),
clientId: config.get<string>('COGNITO_CLIENT_ID'),
clientSecret: config.get<string>('COGNITO_CLIENT_SECRET'),
userPoolId: config.get<string>('COGNITO_USER_POOL_ID'),
appName: config.get<string>('APP_NAME'),
}),
}),
],
})
export class AppModule {}Environment variables (example .env)
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
COGNITO_CLIENT_ID=your_cognito_client_id
COGNITO_CLIENT_SECRET=your_cognito_client_secret
COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
APP_NAME=My AppisGlobal
Setting isGlobal: true registers the module globally so AwsCognitoService is available across all feature modules without re-importing CognitoModule.
All Options
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| region | string | ✅ | — | AWS region of the User Pool |
| accessKeyId | string | ✅ | — | IAM Access Key ID |
| secretAccessKey | string | ✅ | — | IAM Secret Access Key |
| clientId | string | ✅ | — | Cognito App Client ID |
| clientSecret | string | ✅ | — | Cognito App Client Secret |
| userPoolId | string | ✅ | — | Cognito User Pool ID |
| appName | string | ❌ | 'My App' | Used in default email template subjects |
| isGlobal | boolean | ❌ | false | Register module globally |
AWS Cognito Setup Requirements
- Your Cognito App Client must have
ALLOW_ADMIN_USER_PASSWORD_AUTHenabled (forloginandrespondToNewPasswordChallenge). - Your App Client must have a client secret (required for HMAC secret hash computation).
- To use
updateCognitoEmailTemplate, your User Pool's Email Sending Account must be set toDEVELOPER(custom SES integration). - The IAM user/role must have appropriate Cognito permissions (e.g.
cognito-idp:AdminInitiateAuth,cognito-idp:AdminCreateUser, etc.).
Available Services
AwsCognitoService
Inject AwsCognitoService into any provider after importing CognitoModule.
import { Injectable } from '@nestjs/common';
import { AwsCognitoService } from '@nodelabs/nest-aws-cognito';
@Injectable()
export class AuthService {
constructor(private readonly cognitoService: AwsCognitoService) {}
}Methods
login(username, password)
Authenticates a user via ADMIN_USER_PASSWORD_AUTH flow.
const result = await cognitoService.login('[email protected]', 'P@ssword123');Returns on success:
{
accessToken: string;
refreshToken: string;
idToken: string;
expiresIn: number;
tokenType: string;
}Returns when NEW_PASSWORD_REQUIRED challenge is raised:
{
challengeName: 'NEW_PASSWORD_REQUIRED';
session: string;
}Returns null on any other failure.
respondToNewPasswordChallenge(username, newPassword, session)
Completes the NEW_PASSWORD_REQUIRED challenge returned by login.
const result = await cognitoService.respondToNewPasswordChallenge(
'[email protected]',
'NewP@ssword123',
session, // from login() response
);Returns the same token shape as login on success.
register(body)
Self-service user registration via SignUp. Requires unauthenticated access to be enabled on the App Client.
await cognitoService.register({
email: '[email protected]',
password: 'P@ssword123',
firstName: 'Alice',
lastName: 'Smith',
});Payload: IRegisterUserPayload
createUser(body)
Admin-side user creation via AdminCreateUser. Sets email_verified: true and suppresses the default invitation message (use updateCognitoEmailTemplate for custom invitations).
await cognitoService.createUser({
email: '[email protected]',
password: 'TempP@ss123',
firstName: 'Bob',
lastName: 'Jones',
});Payload: ICreateUserPayload
updateUser(cognitoId, body)
Updates user attributes for an existing user.
await cognitoService.updateUser('sub-uuid-here', {
firstName: 'Bobby',
customAttributes: {
'custom:role': 'admin',
'custom:tenantId': 'tenant-123',
},
});Payload: IUpdateUserPayload
forgotPassword(email)
Initiates the forgot-password flow, sending a confirmation code to the user.
await cognitoService.forgotPassword('[email protected]');confirmForgotPassword(email, confirmationCode, newPassword)
Completes the forgot-password flow using the code sent by forgotPassword.
await cognitoService.confirmForgotPassword(
'[email protected]',
'123456',
'NewP@ssword123',
);addToGroup(cognitoId, roles)
Adds a user to one or more Cognito groups in parallel.
await cognitoService.addToGroup('sub-uuid-here', ['admin', 'editor']);updateCognitoEmailTemplate(options)
Updates the User Pool's verification and invitation email templates. The caller is responsible for rendering the HTML strings (e.g. via Handlebars, EJS, or any template engine) before passing them in — keeping this package free of file-system or template-engine dependencies.
Requires
EmailSendingAccountto be set toDEVELOPERin the User Pool.
import Handlebars from 'handlebars';
import * as fs from 'fs';
const verificationTemplate = Handlebars.compile(
fs.readFileSync('templates/verification.hbs', 'utf8'),
);
const invitationTemplate = Handlebars.compile(
fs.readFileSync('templates/invitation.hbs', 'utf8'),
);
await cognitoService.updateCognitoEmailTemplate({
verificationEmailHtml: verificationTemplate({ appName: 'My App' }),
verificationEmailSubject: 'Verify your email — My App',
invitationEmailHtml: invitationTemplate({ appName: 'My App' }),
invitationEmailSubject: 'Your temporary password — My App',
});Note:
verificationEmailHtmlmust include the{####}placeholder so Cognito can inject the verification code.invitationEmailHtmlmust include{####}for the temporary password.
Payload: IUpdateCognitoEmailTemplateOptions
Methods Summary
| Method | Signature | Description |
|--------|-----------|-------------|
| login | login(username: string, password: string): Promise<TokenResult \| ChallengeResult \| null> | Admin password auth |
| respondToNewPasswordChallenge | respondToNewPasswordChallenge(username: string, newPassword: string, session: string): Promise<TokenResult \| undefined> | Complete NEW_PASSWORD_REQUIRED challenge |
| register | register(body: IRegisterUserPayload): Promise<any \| null> | Self-service sign-up |
| createUser | createUser(body: ICreateUserPayload): Promise<any \| null> | Admin user creation |
| updateUser | updateUser(cognitoId: string, body: IUpdateUserPayload): Promise<any \| null> | Update user attributes |
| forgotPassword | forgotPassword(email: string): Promise<ForgotPasswordCommandOutput \| null> | Initiate forgot-password flow |
| confirmForgotPassword | confirmForgotPassword(email: string, confirmationCode: string, newPassword: string): Promise<ConfirmForgotPasswordCommandOutput \| null> | Complete forgot-password flow |
| addToGroup | addToGroup(cognitoId: string, roles: string[]): Promise<any[]> | Add user to Cognito groups |
| updateCognitoEmailTemplate | updateCognitoEmailTemplate(options: IUpdateCognitoEmailTemplateOptions): Promise<any> | Update User Pool email templates |
API Reference
ICognitoModuleOptions
interface ICognitoModuleOptions {
/** AWS region (e.g. 'us-east-1') */
region: string;
/** IAM Access Key ID */
accessKeyId: string;
/** IAM Secret Access Key */
secretAccessKey: string;
/** Cognito App Client ID */
clientId: string;
/** Cognito App Client Secret */
clientSecret: string;
/** Cognito User Pool ID (e.g. 'us-east-1_XXXXXXXXX') */
userPoolId: string;
/** Application name used in default email subjects (default: 'My App') */
appName?: string;
}ICognitoModuleAsyncOptions
interface ICognitoModuleAsyncOptions {
isGlobal?: boolean;
imports?: any[];
inject?: any[];
useFactory: (...args: any[]) => ICognitoModuleOptions | Promise<ICognitoModuleOptions>;
}IRegisterUserPayload
interface IRegisterUserPayload {
email: string;
password: string;
firstName?: string;
lastName?: string;
}ICreateUserPayload
interface ICreateUserPayload {
email: string;
password: string;
firstName?: string;
lastName?: string;
}IUpdateUserPayload
interface IUpdateUserPayload {
email?: string;
firstName?: string;
lastName?: string;
/** Key-value map for custom Cognito attributes (e.g. 'custom:role') */
customAttributes?: Record<string, string>;
}IUpdateCognitoEmailTemplateOptions
interface IUpdateCognitoEmailTemplateOptions {
/**
* Pre-rendered HTML for the verification email.
* Must include {####} placeholder for the verification code.
*/
verificationEmailHtml: string;
/** Subject line for the verification email (default: 'Your verification code - <appName>') */
verificationEmailSubject?: string;
/**
* Pre-rendered HTML for the admin invitation email.
* Must include {####} placeholder for the temporary password.
*/
invitationEmailHtml: string;
/** Subject line for the invitation email (default: 'Your temporary password - <appName>') */
invitationEmailSubject?: string;
}Exports
| Symbol | Description |
|--------|-------------|
| CognitoModule | Dynamic NestJS module (forRoot / forRootAsync) |
| AwsCognitoService | Injectable Cognito service |
| COGNITO_MODULE_OPTIONS | Injection token for options object |
| ICognitoModuleOptions | TypeScript interface for module options |
| ICognitoModuleAsyncOptions | TypeScript interface for async options |
| IRegisterUserPayload | Interface for self-service registration payload |
| ICreateUserPayload | Interface for admin user creation payload |
| IUpdateUserPayload | Interface for user attribute update payload |
License
MIT
