add jwt
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import {Module} from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import {AppController} from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import {AppService} from './app.service';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import {TypeOrmModule} from '@nestjs/typeorm';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import {ConfigModule, ConfigService} from '@nestjs/config';
|
||||||
import * as Joi from 'joi';
|
import * as Joi from 'joi';
|
||||||
import {UsersModule} from "./users/user.module";
|
import {UsersModule} from "./users/user.module";
|
||||||
import {AuthenticationModule} from "./authentication/authentication.module";
|
import {AuthenticationModule} from "./authentication/authentication.module";
|
||||||
import { PostsModule } from './posts/posts.module';
|
import {PostsModule} from './posts/posts.module';
|
||||||
import { CategoriesModule } from './categories/categories.module';
|
import {CategoriesModule} from './categories/categories.module';
|
||||||
import {FilesModule} from "./files/file.module";
|
import {FilesModule} from "./files/file.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@@ -36,6 +36,10 @@ import {FilesModule} from "./files/file.module";
|
|||||||
S3_BUCKET: Joi.string().required(),
|
S3_BUCKET: Joi.string().required(),
|
||||||
S3_ACCESS_KEY: Joi.string().required(),
|
S3_ACCESS_KEY: Joi.string().required(),
|
||||||
S3_ENDPOINT: Joi.string().required(),
|
S3_ENDPOINT: Joi.string().required(),
|
||||||
|
JWT_ACCESS_TOKEN_SECRET: Joi.string().required(),
|
||||||
|
JWT_ACCESS_TOKEN_EXPIRATION_TIME: Joi.string().required(),
|
||||||
|
JWT_REFRESH_TOKEN_SECRET: Joi.string().required(),
|
||||||
|
JWT_REFRESH_TOKEN_EXPIRATION_TIME: Joi.string().required(),
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
UsersModule,
|
UsersModule,
|
||||||
@@ -47,4 +51,5 @@ import {FilesModule} from "./files/file.module";
|
|||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {
|
||||||
|
}
|
||||||
@@ -17,12 +17,12 @@ import JwtAuthenticationGuard from './jwt-authentication.guard';
|
|||||||
// import {EmailConfirmationService} from '../emailConfirmation/emailConfirmation.service';
|
// import {EmailConfirmationService} from '../emailConfirmation/emailConfirmation.service';
|
||||||
import {ApiBody} from '@nestjs/swagger';
|
import {ApiBody} from '@nestjs/swagger';
|
||||||
import LogInDto from './dto/logIn.dto';
|
import LogInDto from './dto/logIn.dto';
|
||||||
import { UsersService } from 'src/users/user.service';
|
import {UsersService} from 'src/users/user.service';
|
||||||
|
|
||||||
@Controller('authentication')
|
@Controller('authentication')
|
||||||
@UseInterceptors(ClassSerializerInterceptor)
|
@UseInterceptors(ClassSerializerInterceptor)
|
||||||
@SerializeOptions({
|
@SerializeOptions({
|
||||||
strategy: 'excludeAll'
|
strategy: 'excludeAll'
|
||||||
})
|
})
|
||||||
export class AuthenticationController {
|
export class AuthenticationController {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -87,4 +87,14 @@ export class AuthenticationController {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(JwtRefreshGuard)
|
||||||
|
@Get('refresh')
|
||||||
|
refresh(@Req() request: RequestWithUser) {
|
||||||
|
const accessTokenCookie = this.authenticationService.getCookieWithJwtAccessToken(request.user.id);
|
||||||
|
|
||||||
|
request.res.setHeader('Set-Cookie', accessTokenCookie);
|
||||||
|
return request.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
30
src/authentication/jwt-refresh-token.strategy.ts
Normal file
30
src/authentication/jwt-refresh-token.strategy.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||||
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { Request } from 'express';
|
||||||
|
import {UsersService} from "../users/user.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class JwtRefreshTokenStrategy extends PassportStrategy(
|
||||||
|
Strategy,
|
||||||
|
'jwt-refresh-token'
|
||||||
|
) {
|
||||||
|
constructor(
|
||||||
|
private readonly configService: ConfigService,
|
||||||
|
private readonly userService: UsersService,
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
jwtFromRequest: ExtractJwt.fromExtractors([(request: Request) => {
|
||||||
|
return request?.cookies?.Refresh;
|
||||||
|
}]),
|
||||||
|
secretOrKey: configService.get('JWT_REFRESH_TOKEN_SECRET'),
|
||||||
|
passReqToCallback: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(request: Request, payload: TokenPayload) {
|
||||||
|
const refreshToken = request.cookies?.Refresh;
|
||||||
|
return this.userService.getUserIfRefreshTokenMatches(refreshToken, payload.userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/authentication/jwtRefreshGuard.guard.ts
Normal file
5
src/authentication/jwtRefreshGuard.guard.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export default class JwtRefreshGuard extends AuthGuard('jwt-refresh-token') {}
|
||||||
@@ -34,6 +34,19 @@ export class UsersService {
|
|||||||
throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND);
|
throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getUserIfRefreshTokenMatches(refreshToken: string, userId: number) {
|
||||||
|
const user = await this.getById(userId);
|
||||||
|
|
||||||
|
const isRefreshTokenMatching = await bcrypt.compare(
|
||||||
|
refreshToken,
|
||||||
|
user.currentHashedRefreshToken
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isRefreshTokenMatching) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async addAvatar(userId: number, imageBuffer: Buffer, filename: string) {
|
async addAvatar(userId: number, imageBuffer: Buffer, filename: string) {
|
||||||
const avatar = await this.filesService.uploadPublicFile(imageBuffer, filename);
|
const avatar = await this.filesService.uploadPublicFile(imageBuffer, filename);
|
||||||
const user = await this.getById(userId);
|
const user = await this.getById(userId);
|
||||||
@@ -62,5 +75,4 @@ export class UsersService {
|
|||||||
currentHashedRefreshToken: null,
|
currentHashedRefreshToken: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user