
서버는 인증을 증명하기 위해 후속요청시 인증헤더에 전달자 토큰으로 전송될 수 있는 jwt 발행
또한 유효한 jwt가 포함된 요청에만 엑세스 할 수 있는 보호된 경로 생성
authmodule,AuthService, AuthController을 실행하는 것부터 시작
$ nest g module auth
$ nest g controller auth
$ nest g service auth
AuthService에서 사용자를 검색하고 비밀번호를 확인하는 작업을 진행
서비스파일에 로그인 하기 위한 함수를 만든다
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UsersService } from '../users/users.service';
@Injectable()
export class AuthService {
constructor(private usersService: UsersService) {}
async signIn(username: string, pass: string): Promise<any> {
const user = await this.usersService.findOne(username);
if (user?.password !== pass) {
throw new UnauthorizedException();
}
const { password, ...result } = user;
// TODO: Generate a JWT and return it here
// instead of the user object
return result;
}
}
여기에 있는 유저 서비스에서 한명 검색하는걸 가져와
async findOne(username: string): Promise<User | undefined> {
return this.users.find(user => user.username === username);
검색하고 확인
인증시스템을 jwt 사용
npm install --save @nestjs/jwt
jwt를 발행하는 코드를 서비스계층에 추가한다
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService
) {}
async signIn(
username: string,
pass: string,
): Promise<{ access_token: string }> {
const user = await this.usersService.findOne(username);
if (user?.password !== pass) {
throw new UnauthorizedException();
}
const payload = { sub: user.userId, username: user.username };
return {
access_token: await this.jwtService.signAsync(payload),
};
}
}
맨 밑에 jwt를 생성하는 함수를 사용
auth폴더에 contants.ts을 만들어 jwt설정을 위한 상수정의
export const jwtConstants = {
secret: 'yourSecretKey', // 여기에 당신의 비밀 키를 입력하세요
};
dlgn authmodule을 업데이트 해 필요한 의존성을 가져오고 jwtmodule 설정
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { jwtConstants } from './constants';
import { JwtStrategy } from './jwt.strategy';
@Module({
imports: [
PassportModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
UsersModule,
],
providers: [AuthService, JwtStrategy],
exports: [AuthService],
})
export class AuthModule {}
jwt검증하기 위해 검증 미들웨어 구현
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { jwtConstants } from './constants';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtConstants.secret,
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
경로를 보호하기 위해 인증가드를 구현하기 위해 인증가드 구현
auth.guards.ts를 만든 다음
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { Request } from 'express';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
if (!token) {
throw new UnauthorizedException();
}
try {
const payload = await this.jwtService.verifyAsync(
token,
{
secret: jwtConstants.secret
}
);
// 💡 We're assigning the payload to the request object here
// so that we can access it in our route handlers
request['user'] = payload;
} catch {
throw new UnauthorizedException();
}
return true;
}
private extractTokenFromHeader(request: Request): string | undefined {
const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}
}
보호하고 싶은 컨트롤러에 가서 적용한다
@UseGuards(AuthGuard)
@Get('profile')
getProfile(@Request() req) {
return req.user;