[nest.js] jwt token 과 cookie 를 이용한 login 구현

jwt 를 이용하여 인증하는 api application은 local test가 불편하다.

인증시 token이 bearer token 형태일 경우

postman 에서 매번 login 후 token 값 알아내기 -> api 마다 수동으로 token 값 넣기 식으로 진행된다.

cookie 에 token 을 넣고 알아서 인증단계를 거치면 이런 노가다가 필요없다.

사전준비

패키지를 설치해 준다.

npm i --save cookie-parser
npm i --save-dev @types/cookie-parser
npm i --save @nestjs/jwt @nestjs/passport passport passport-jwt

main.ts 에 cookie parser 를 사용하도록 설정한다.

app.use( cookieParser() );

tsconfig.json 아래 내용을 추가해 준다.

"esModuleInterop": true

jwt strategy 작성

cookieExtractor 라는 함수만 보면 된다. 내용은 request 의 cookie 에 저장된 token 에 접근하는 것이다.

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 : process.env.JWT_SECRET || jwtConfig.get( "secret" ),
			jwtFromRequest : cookieExtractor
		} );
	}
    
    async validate( payload ) : Promise<UserDTO>
	{
		const { id } = payload;
		// const uid : string = payload["uid"];
		const user : UserDTO = await this.userService.findOne( { id : id } );

		if( !user )
			throw new UnauthorizedException( 'not user' );

		return user;
	}
}

auth.module.ts 에 import 추가
PassportModule.register( { defaultStrategy : "jwt" } ),
JwtModule.register
(
    {
        secret : process.env.JWT_SECRET_KEY
        signOptions : { expiresIn : process.env.EXPIRES_IN }
    }
),

login 시 cookie 에 token 저장

controller 의 response 객체에 jwt service로 발급받은 token 을 저장한다

@Post( '/login' )
	async login(
		@Body( ValidationPipe ) dto: UserDTO,
		@Res( { passthrough : true } ) res : Response
	) : Promise<object>
	{
		const accessToken : object = await this.authService.login( dto );
		res.cookie(
			'Authentication',
			accessToken['token'],
			{
				domain : 'localhost',
				path : '/',
				httpOnly : true,
				maxAge : 0.5 * 60 * 60 * 1000//0.5 hour
			}
			);
		return accessToken;
	}
auth controller
async login( dto: UserDTO ): Promise<object>
	{	
    	.
        .
        .
        
    	const payload = { id : user.id }
		const token = await this.jwtService.sign( payload );

		return {
			'msg' : 'ok',
			'token' : token
		};
	}
auth service

사용예시

@UseGuards decorator 로 주입된 controller 함수를 사용할 경우 자동으로 인증처리가 된다.

@Get( '/myinfo' )
	@UseGuards( AuthGuard() )
	getUser( @GetUser() user : User ) : User
	{
		return user;
	}

Subscribe to X세대 신입사원

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe
774-86-01972 cinnabar.3d@gmail.com