@tresdoce-nestjs-toolkit/auth
v0.2.0
Published
Tresdoce NestJS Toolkit - Módulo de autenticación JWT con roles y refresh tokens
Maintainers
Readme
Este módulo está pensado para ser utilizado en NestJS Starter, o cualquier proyecto que utilice una configuración centralizada, siguiendo la misma arquitectura del starter.
Provee autenticación JWT lista para usar: estrategia y guard de Passport, decorador @CurrentUser(), y un
TokenService con emisión y rotación de refresh tokens persistidos en Redis. Se integra directamente con
@Public() y @Roles() de @tresdoce-nestjs-toolkit/core.
Glosario
- 🥳 Demo
- 📝 Requerimientos básicos
- 🛠️ Instalar dependencia
- ⚙️ Configuración
- 👨💻 Uso
- 📖 API Reference
- 📄 Changelog
- 📜 License MIT
📝 Requerimientos básicos
- NestJS Starter
- Node.js v22.21.1 or higher (Download)
- YARN ≥ 1.22.22 o NPM ≥ 11.6.4
- NestJS v11.1.11 or higher (Documentación)
- Redis 5.0 or higher (persistencia de refresh tokens)
🛠️ Instalar dependencia
npm install -S @tresdoce-nestjs-toolkit/authyarn add @tresdoce-nestjs-toolkit/auth📦 Dependencias internas
Este paquete usa @tresdoce-nestjs-toolkit/core (para @Public()/@Roles()/IS_PUBLIC_KEY) y
@tresdoce-nestjs-toolkit/redis (para persistir los refresh tokens). El RedisModule debe estar
registrado en la aplicación —típicamente vía RedisModule.register(...) o configuración centralizada
en app.module.ts— antes de importar AuthModule, ya que TokenService depende de RedisService.
⚙️ Configuración
AuthModule se registra con AuthModule.register(options), sin depender de ConfigService, para
mantener explícito de dónde sale el secreto de firma:
//./src/config/configuration.ts
import { Typings } from '@tresdoce-nestjs-toolkit/core';
import { registerAs } from '@nestjs/config';
export default registerAs('config', (): Typings.AppConfig => {
return {
//...
auth: {
jwtSecret: process.env.JWT_SECRET,
accessTokenTtl: process.env.JWT_ACCESS_TOKEN_TTL || '15m',
refreshTokenTtlSeconds:
parseInt(process.env.JWT_REFRESH_TOKEN_TTL_SECONDS, 10) || 60 * 60 * 24 * 7,
},
//...
};
});jwtSecret: Secreto usado para firmar y verificar el access token.
- Type:
String - Required:
true
accessTokenTtl: Tiempo de vida del access token, en formato aceptado por @nestjs/jwt (ej. '15m', '1h').
- Type:
String - Required:
false - Default:
'15m'
refreshTokenTtlSeconds: Tiempo de vida del refresh token, en segundos.
- Type:
Number - Required:
false - Default:
604800(7 días)
👨💻 Uso
Importación del módulo
//./src/app.module.ts
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthModule } from '@tresdoce-nestjs-toolkit/auth';
import { RedisModule } from '@tresdoce-nestjs-toolkit/redis';
@Module({
imports: [
//...
RedisModule, // debe registrarse antes que AuthModule
AuthModule.register({
jwtSecret: process.env.JWT_SECRET,
accessTokenTtl: '15m',
refreshTokenTtlSeconds: 60 * 60 * 24 * 7,
}),
//...
],
})
export class AppModule {}AuthModule registra JwtAuthGuard como APP_GUARD: todas las rutas quedan protegidas por defecto y
requieren un access token válido en el header Authorization: Bearer <token>. Para exponer una ruta
pública, usar @Public() de @tresdoce-nestjs-toolkit/core:
import { Controller, Get } from '@nestjs/common';
import { Public } from '@tresdoce-nestjs-toolkit/core';
@Controller('auth')
export class AuthController {
@Public()
@Get('health')
health() {
return { status: 'ok' };
}
}Emitir tokens (login)
import { Body, Controller, Post } from '@nestjs/common';
import { Public } from '@tresdoce-nestjs-toolkit/core';
import { TokenService } from '@tresdoce-nestjs-toolkit/auth';
@Controller('auth')
export class AuthController {
constructor(private readonly tokenService: TokenService) {}
@Public()
@Post('login')
async login(@Body() dto: LoginDto) {
const user = await this.usersService.validateCredentials(dto);
return this.tokenService.generateTokens({ id: user.id, email: user.email, roles: user.roles });
}
}Rotar el refresh token
El refresh token es de un solo uso: al canjearlo se invalida y se emite un par nuevo.
@Public()
@Post('refresh')
async refresh(@Body('refreshToken') refreshToken: string) {
return this.tokenService.refreshTokens(refreshToken);
}Logout / revocación
@Post('logout')
async logout(@Body('refreshToken') refreshToken: string) {
await this.tokenService.revokeRefreshToken(refreshToken);
}
@Post('logout-all')
async logoutAll(@CurrentUser('id') userId: string) {
await this.tokenService.revokeAllForUser(userId);
}Leer el usuario autenticado con @CurrentUser()
import { Controller, Get } from '@nestjs/common';
import { CurrentUser, IAuthenticatedUser } from '@tresdoce-nestjs-toolkit/auth';
@Controller('profile')
export class ProfileController {
@Get('me')
me(@CurrentUser() user: IAuthenticatedUser) {
return user;
}
@Get('me/id')
myId(@CurrentUser('id') id: string) {
return { id };
}
}Combinación con @Roles()
request.user.roles queda poblado por JwtStrategy, por lo que RolesGuard de
@tresdoce-nestjs-toolkit/core funciona sin configuración adicional:
import { Controller, Delete, Param, UseGuards } from '@nestjs/common';
import { Roles, RolesGuard } from '@tresdoce-nestjs-toolkit/core';
@Controller('users')
@UseGuards(RolesGuard)
export class UsersController {
@Roles('admin')
@Delete(':id')
remove(@Param('id') id: string) {
//...
}
}📖 API Reference
AuthModule
| Método | Descripción |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| AuthModule.register(options: AuthModuleOptions) | Inicialización estática. Registra PassportModule, JwtModule, JwtStrategy, TokenService y JwtAuthGuard (como APP_GUARD). |
TokenService
| Método | Firma | Descripción |
| -------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- |
| generateTokens | (user: IAuthenticatedUser) => Promise<IAuthTokens> | Emite un nuevo par access/refresh token y persiste el refresh en Redis |
| refreshTokens | (refreshToken: string) => Promise<IAuthTokens> | Rota un refresh token vigente (uso único) y emite un par nuevo |
| revokeRefreshToken | (refreshToken: string, userId?: string) => Promise<void> | Revoca un refresh token puntual |
| revokeAllForUser | (userId: string) => Promise<void> | Revoca todos los refresh tokens vigentes de un usuario |
JwtStrategy / JwtAuthGuard
JwtStrategy extrae el bearer token, lo verifica contra jwtSecret y mapea el payload a
IAuthenticatedUser (sub → id), quedando disponible en request.user.
JwtAuthGuard extiende AuthGuard('jwt') de Passport y respeta @Public(): las rutas marcadas
como públicas omiten la validación del token.
CurrentUser
Decorador de parámetro. Sin argumentos devuelve el IAuthenticatedUser completo; con una key
(@CurrentUser('id')) devuelve solo ese campo.
Interfaces
| Interfaz | Descripción |
| -------------------- | ---------------------------------------------------------------------------- |
| IJwtPayload | Payload firmado en el access token (sub, email?, roles?, claims extra) |
| IAuthenticatedUser | Shape de request.user (id, email?, roles?, campos extra) |
| IAuthTokens | { accessToken: string; refreshToken: string } |
| AuthModuleOptions | Opciones de AuthModule.register() |
Constantes exportadas
| Constante | Descripción |
| --------------------------------- | -------------------------------------------------------------------- |
| AUTH_MODULE_OPTIONS | Token de inyección de las opciones del módulo |
| REFRESH_TOKEN_PREFIX | Prefijo de la key de Redis usada para persistir cada refresh token |
| REFRESH_TOKEN_USER_INDEX_PREFIX | Prefijo de la key de Redis usada para indexar los tokens por usuario |
📄 Changelog
Todos los cambios notables de este paquete se documentarán en el archivo Changelog.
