Skip to content

Instantly share code, notes, and snippets.

@muneneevans
Forked from acabreragnz/auth.ts
Created September 7, 2022 11:28
Show Gist options
  • Save muneneevans/23771ab5ab0e141f947003c24c7eadf3 to your computer and use it in GitHub Desktop.
Save muneneevans/23771ab5ab0e141f947003c24c7eadf3 to your computer and use it in GitHub Desktop.
Authentication in Nestjs using JWT and Local strategires
# src/api/auth/passport/jwt.strategy.ts
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { ConfigService } from 'src/api/config/config.service';
import { UsersProvider } from 'src/api/users/users.provider';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly configService: ConfigService,
private readonly usersProvider: UsersProvider,
private readonly jwtService: JwtService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: true,
secretOrKey: configService.getJWTSecret(),
});
}
async validate(payload: any) {
const accessToken = this.jwtService.sign(payload);
if (await this.usersProvider.validateToken(accessToken, payload.sub)) {
return { userId: payload.sub, username: payload.username };
} else {
throw new Error('Token validation error.');
}
}
}
# src/api/auth/passport/local.strategy.ts
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import {
Injectable,
UnauthorizedException,
BadRequestException,
} from '@nestjs/common';
import { AuthProvider } from '../auth.provider';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly authProvider: AuthProvider) {
super({ passReqToCallback: true });
}
async validate(payload: any): Promise<any> {
const request = payload;
if (request.body && request.body.username && request.body.password) {
const user = await this.authProvider.validateUser(
request.body.username,
request.body.password,
);
if (!user) {
throw new UnauthorizedException();
}
return user;
} else {
throw new BadRequestException();
}
}
}
# src/api/auth/auth.module.ts
import { Module } from '@nestjs/common';
import { AuthProvider } from './auth.provider';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './passport/jwt.strategy';
import { UserEntity } from 'src/implementations/entities/user.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '../config/config.module';
import { ConfigService } from '../config/config.service';
import { AuthController } from './auth.controller';
import { UsersModule } from '../users/users.module';
import { LocalStrategy } from './passport/local.strategy';
@Module({
imports: [
ConfigModule,
TypeOrmModule.forFeature([UserEntity]),
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
secret: configService.getJWTSecret(),
}),
inject: [ConfigService],
}),
UsersModule,
],
providers: [AuthProvider, JwtStrategy, LocalStrategy],
controllers: [AuthController],
exports: [AuthProvider],
})
export class AuthModule {}
# src/api/auth/auth.controller.ts
import {
Controller,
Request,
Post,
UseGuards,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthProvider } from './auth.provider';
import { loggerService } from 'src/main';
@Controller('auth')
export class AuthController {
constructor(private readonly authProvider: AuthProvider) {}
@UseGuards(AuthGuard('local'))
@Post('login')
async login(@Request() req: any) {
try {
return this.authProvider.login(req.user);
} catch (error) {
const errMsg = `There was a error logging in. Error: ${error}.`;
loggerService.error(errMsg);
throw new HttpException(errMsg, HttpStatus.UNAUTHORIZED);
}
}
@UseGuards(AuthGuard('jwt'))
@Post('logout')
async logout(@Request() req: any) {
try {
return this.authProvider.logout(req.user.userId);
} catch (error) {
const errMsg = `There was a error logging out. Error: ${error}.`;
loggerService.error(errMsg);
throw new HttpException(errMsg, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
# src/api/auth/auth.provider.ts
import { Injectable } from '@nestjs/common';
import { UsersProvider } from '../users/users.provider';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthProvider {
constructor(
private readonly usersProvider: UsersProvider,
private readonly jwtService: JwtService,
) {}
public async validateUser(username: string, pass: string): Promise<any> {
return this.usersProvider.validateCredentials(username, pass);
}
public async login(user: any) {
const payload = { username: user.username, sub: user.id };
const accessToken = this.jwtService.sign(payload);
await this.usersProvider.saveToken(accessToken, user.id);
return {
accessToken,
};
}
public async logout(userId: number): Promise<boolean> {
return this.usersProvider.removeToken(userId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment