- Published on
π Simplified Guide to JWT Authentication with NestJS
Simplified Guide to JWT Authentication with NestJS π
Introduction
In today's digital world, securing your applications is essential. One effective method to ensure user identity verification is through JWT (JSON Web Token) authentication. In this guide, we'll implement JWT authentication in a NestJS application, focusing on controllers, services, configurations, and repositories. Letβs enhance your app's security step by step!
π Step 1: Setting Up Your NestJS Project
Start by creating a new NestJS project. You can do this using the Nest CLI:
npm i -g @nestjs/cli
nest new your-project-name
Next, install the necessary dependencies for JWT authentication:
npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcryptjs
npm install --save-dev @types/passport-jwt
π¦ Step 2: Creating User Entity and Repository
Create a User
entity to hold user data such as id
, username
, and password
. You can use TypeORM for database interactions.
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
username: string;
@Column()
password: string;
}
Next, create a UserRepository
using TypeORM:
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findByUsername(username: string): Promise<User | undefined> {
return this.findOne({ where: { username } });
}
}
π Step 3: Configuring AuthModule
Set up a new module called AuthModule
and configure it for JWT authentication.
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
@Module({
imports: [
UsersModule,
JwtModule.register({
secret: 'your-secret-key', // Replace with a secure secret
signOptions: { expiresIn: '15m' },
}),
],
providers: [AuthService],
exports: [AuthService],
})
export class AuthModule {}
π€ Step 4: Implementing AuthService
Create the AuthService
to handle user registration and authentication.
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from './user.entity';
import { UserRepository } from './user.repository';
import * as bcrypt from 'bcrypt';
@Injectable()
export class AuthService {
constructor(
private readonly userRepository: UserRepository,
private readonly jwtService: JwtService
) {}
async register(username: string, password: string): Promise<User> {
const hashedPassword = await bcrypt.hash(password, 10);
const user = this.userRepository.create({ username, password: hashedPassword });
return this.userRepository.save(user);
}
async validateUser(username: string, password: string): Promise<any> {
const user = await this.userRepository.findByUsername(username);
if (user && (await bcrypt.compare(password, user.password))) {
const { password, ...result } = user; // Exclude password from the response
return result;
}
return null;
}
async login(user: User) {
const payload = { username: user.username, sub: user.id };
return {
access_token: this.jwtService.sign(payload),
};
}
}
π Step 5: Creating AuthController
Create an AuthController
to handle registration and login requests.
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('register')
async register(@Body() body: { username: string; password: string }) {
const user = await this.authService.register(body.username, body.password);
return { message: 'User registered successfully!', user };
}
@Post('login')
async login(@Body() body: { username: string; password: string }) {
const user = await this.authService.validateUser(body.username, body.password);
if (!user) {
return { message: 'Invalid username or password' };
}
return this.authService.login(user);
}
}
π Step 6: Implementing JWT Strategy
Create a JwtStrategy
to validate JWT tokens on incoming requests.
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { JwtPayload } from './jwt-payload.interface';
import { UsersService } from '../users/users.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private readonly usersService: UsersService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: 'your-secret-key', // Same as in AuthModule
});
}
async validate(payload: JwtPayload) {
return this.usersService.findById(payload.sub);
}
}
π Conclusion Keep in mind that security is an ongoing process, so always stay updated with best practices to further enhance your applicationβs defenses. Happy coding, and stay secure! ππ