A progressive Node.js framework for building efficient and scalable server-side applications.
Nest framework TypeScript base auth module.
$ npm install --save @peersyst/auth-module
- Import and register AuthModule in AppModule
import { AuthModule } from "@peersyst/auth-module";
@Module({
imports: [
ConfigModule.forRoot(...),
TypeOrmModule.forRootAsync(...),
UserModule,
AuthModule.register(UserModule, ConfigModule, ConfigService, {}),
],
})
export class AppModule {}
- UserModule should export a provider named UserService
@Module({
imports: [
TypeOrmModule.forFeature([User]),
],
providers: [MyUserService, { provide: "UserService", useClass: MyUserService }],
controllers: [UserController],
exports: [MyUserService, { provide: "UserService", useClass: MyUserService }, TypeOrmModule],
})
export class UserModule {}
- Add configService configuration variables
export default (): any => ({
server: {
secretKey: process.env.APP_JWT_KEY, ...
},
});
- Add AuthErrorCode and AuthErrorBody to app ErrorCodes
import { HttpStatus } from "@nestjs/common";
import { AuthErrorCode, AuthErrorBody } from "@peersyst/auth-module";
// Define app error codes
enum AppErrorCode {}
export const ErrorCode = { ...AppErrorCode, ...AuthErrorCode };
export type ErrorCodeType = AppErrorCode | AuthErrorCode;
export const ErrorBody: { [code in ErrorCodeType]: { statusCode: HttpStatus; message: string } } = {
// Define app error code bodies
...AuthErrorBody,
};
- Implement AuthUserI for User entity
import { AuthUserI, UserType } from "@peersyst/auth-module";
@Entity("user")
export class User implements AuthUserI {...}
- Implement AuthUserServiceI for UserService
import { AuthUserServiceI } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI {...}
- Use authenticated in controllers
import { Authenticated } from "@peersyst/auth-module";
@ApiTags("user")
@Controller("users")
@ApiErrorDecorators()
export class UserController {
constructor(private readonly userService: UserService) {}
@Authenticated(UserType.ADMIN)
@Post("create")
@ApiOperation({ summary: "Create user" })
async create(@Body() createUserRequestDto: CreateUserRequest): Promise<UserDto> {
return this.userService.createUser(createUserRequestDto);
}
@Authenticated()
@Get("info")
@ApiOperation({ summary: "Show user info" })
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
async info(@Request() req): Promise<UserDto> {
return this.userService.findById(req.user.id);
}
}
- Set googleAuth to true in register module
AuthModule.register(UserModule, ConfigModule, ConfigService, {
googleAuth: true,
}),
- Add configService configuration variables
export default (): any => ({
server: {
secretKey: process.env.APP_JWT_KEY,
frontUrl: process.env.FRONT_URL,
baseUrl: process.env.BASE_URL,
},
googleAuth: {
clientId: process.env.GOOGLE_AUTH_CLIENT_ID,
clientSecret: process.env.GOOGLE_AUTH_CLIENT_SECRET,
},
});
- Implement AuthGoogleUserI for User entity
import { AuthUserI, AuthGoogleUserI, UserType } from "@peersyst/auth-module";
@Entity("user")
export class User implements AuthUserI, AuthGoogleUserI {...}
- Implement ThirdPartyUserServiceI for UserService
import { AuthUserServiceI, ThirdPartyUserServiceI } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI, ThirdPartyUserServiceI {...}
- Set twitterAuth to true in register module
AuthModule.register(UserModule, ConfigModule, ConfigService, {
twitterAuth: true,
}),
- Add configService configuration variables
export default (): any => ({
server: {
secretKey: process.env.APP_JWT_KEY,
frontUrl: process.env.FRONT_URL,
baseUrl: process.env.BASE_URL,
},
twitterAuth: {
apiKey: process.env.TWITTER_API_KEY,
apiKeySecret: process.env.TWITTER_API_KEY_SECRET,
},
});
- Implement AuthTwitterUserI for User entity
import { AuthUserI, AuthTwitterUserI, UserType } from "@peersyst/auth-module";
@Entity("user")
export class User implements AuthUserI, AuthTwitterUserI {...}
- Implement ThirdPartyUserServiceI for UserService
import { AuthUserServiceI, ThirdPartyUserServiceI } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI, ThirdPartyUserServiceI {...}
- Set validateEmail to true in register module
AuthModule.register(UserModule, ConfigModule, ConfigService, {
validateEmail: true,
}),
- Implement ValidateEmailUserServiceI for UserService
import { AuthUserServiceI, ValidateEmailUserServiceI } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI, ValidateEmailUserServiceI {...}
- When you either create or register a user an email verification token should be created and sent:
import { AuthUserServiceI, ValidateEmailUserServiceI, TokenService } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI, ValidateEmailUserServiceI {
constructor(
@InjectRepository(User) private readonly userRepository: Repository<User>,
@Inject(NotificationService) private readonly notificationService: NotificationService,
@Inject(ValidateEmailService) private readonly validateEmailService: ValidateEmailService,
) {}
async registerUser(registerUserRequest: RegisterUserRequest): Promise<PrivateUserDto> {
const entity = await this.userRepository.save(registerUserRequest);
const user = PrivateUserDto.fromEntity(entity);
const token = await this.validateEmailService.createEmailVerificationToken(user.id);
await this.notificationService.sendEmailVerificationMessage(createUserRequest.email, token);
}
}
- Create entity in your entities folder with name VerifyEmailToken
export { VerifyEmailToken } from "@peersyst/auth-module";
- Set recoverPassword to true in register module and indicate NotificationModule.
AuthModule.register(UserModule, ConfigModule, ConfigService, {
recoverPassword: true,
NotificationModule,
}),
NotificationModule should export a provider named NotificationService (v8 onwards):
@Module({
providers: [NotificationService, { provide: "NotificationService", useClass: NotificationService }],
exports: [NotificationService, { provide: "NotificationService", useClass: NotificationService }],
})
export class NotificationModule {}
- Implement RecoverNotificationServiceI for NotificationService
import { RecoverNotificationServiceI } from "@peersyst/auth-module";
@Injectable()
export class NotificationService implements RecoverNotificationServiceI {...}
- Implement RecoverPasswordUserServiceI for UserService
import { AuthUserServiceI, RecoverPasswordUserServiceI } from "@peersyst/auth-module";
@Injectable()
export class UserService implements AuthUserServiceI, RecoverPasswordUserServiceI {...}
- Create entity in your entities folder with name ResetToken
export { ResetToken } from "@peersyst/auth-module";
- Set twoFA to true in register module
AuthModule.register(UserModule, ConfigModule, ConfigService, {
twoFA: true,
}),
- Implement Auth2FAUserI for User entity
import { AuthUserI, Auth2FAUserI, UserType } from "@peersyst/auth-module";
@Entity("user")
export class User implements AuthUserI, Auth2FAUserI {...}
Nest is MIT licensed.