[nest.js] jwt를 이용해서 request 에 사용자 정보 넣기
회원기반 사이트는 반드시 인증이 필요하다.
웹개발에서 jwt라는 쉬운 방법이 있는데 nest.js에서도 지원이 된다.
local에서는 jwt로 발급된 token을 bearer token 이나 cookie를 이용하여 테스트 할 수 있다.
cookie를 이용한 방법을 소개한다.
a. strategy
인증을 담당하는 module에 import할 strategy 클래스 작성
validate에서 return되는 객체는 request 에 담겨진다.
import { Injectable, NotFoundException, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "../user/user.entity";
let cookieExtractor = function( req )
{
var token = null;
if ( req && req.cookies )
{
token = req.cookies["Authentication"] || req.header;
}
return token;
};
@Injectable()
export class JwtStrategy extends PassportStrategy( Strategy )
{
constructor( @InjectRepository( User ) private userRepository : Repository<User> )
{
super(
{
secretOrKey : "secret1234",
jwtFromRequest : cookieExtractor
} );
};
async validate( payload ) : Promise<User>
{
const { id } = payload;
const user : User = await this.userRepository.findOneBy( { id : id } );
if ( !user )
throw new UnauthorizedException( "음는 사람인디요" );
return user;
}
}
b. decorator 작성
GetUser라는 decorator를 작성한다. 이렇게 하면 request 를 통하지 않고도 controller 에서 @GetUser 로 주입된 parameter를 통해 쉽게 user 객체에 접근이 가능해진다.
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { User } from "../user/user.entity";
export const GetUser = createParamDecorator( ( data, ctx : ExecutionContext ) : User =>
{
const req = ctx.switchToHttp().getRequest();
return req.user;
} )
c. module
사용하려는 module 에 strategy 클래스에서 설정한 동일한 secret 값으로 등록한다.
import { Module } from "@nestjs/common";
import { AuthController } from "./auth.controller";
import { AuthService } from "./auth.service";
import { UserHttpModule } from "../user/user-http.module";
import { JwtModule } from "@nestjs/jwt";
import { PassportModule } from "@nestjs/passport";
import { JwtStrategy } from "./jwt.strategy";
import { TypeOrmModule } from "@nestjs/typeorm";
import { User } from "../user/user.entity";
@Module( {
imports : [
TypeOrmModule.forFeature([User]),
PassportModule.register({ defaultStrategy : 'jwt'} ),
JwtModule.register(
{
secret : 'secret1234',
signOptions : { expiresIn : 3600 }
}
),
UserHttpModule],
controllers : [AuthController],
providers : [AuthService, JwtStrategy],
exports : [JwtStrategy, PassportModule]
} )
export class AuthModule {}
d. controller 사용 예시
@GetUser 로 주입된 parameter 를 통해 user 객체에 접근이 가능하다.
@Post()
async save( @GetUser() user : User, @Body() board : Board ): Promise<Board>
{
return await this.boardService.insert( board, user );
}