npm install bcryptjs --save
# import * as bcrypt from 'bcryptjs'
async createUser(authCredentialsDto: AuthCredentialsDto): Promise<void> {
const { username, password } = authCredentialsDto;
const salt = await bcrypt.genSalt();
const hashedPassword = await bcrypt.hash(password, salt);
const user = this.create({ username, password: hashedPassword });
...
} async signIn(authCredentialsDto: AuthCredentialsDto): Promise<string> {
const { username, password } = authCredentialsDto;
const user = await this.userRepository.findOne({ where: { username } });
if (user && (await bcrypt.compare(password, user.password))) {
return 'logIn success';
} else {
throw new UnauthorizedException('logIn failed');
}
}
@Post('/signin')
signIn(@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto) {
return this.authService.signIn(authCredentialsDto);
}
pnpm install @nestjs/jwt @nestjs/passport passport passport-jwt @types/passport-jwt --save


jwt로 설정 secret과 signOptions 설정@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: 'Secret1234',
signOptions: {
expiresIn: 3600,
},
}),
TypeOrmModule.forFeature([UserRepository]),
],
controllers: [AuthController],
providers: [AuthService, UserRepository],
})
export class AuthModule {}
service
생성자에 jwtService 추가
private jwtService: JwtService,
jwtService.sign(payload) : sign 메서드는 내부적으로 header, payload, secret text(환경설정에서 정의된)를 사용하여 JWT 생성한다. (내부적으로 복잡한 과정을 단순화)
async signIn(
authCredentialsDto: AuthCredentialsDto,
): Promise<{ accessToken: string }> {
const { username, password } = authCredentialsDto;
const user = await this.userRepository.findOne({ where: { username } });
if (user && (await bcrypt.compare(password, user.password))) {
const payload = { username };
const accessToken = await this.jwtService.sign(payload);
return { accessToken };
} else {
throw new UnauthorizedException('logIn failed');
}
}
controller : 반환타입 추가
@Post('/signin')
signIn(
@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto,
): Promise<{ accessToken: string }> {
return this.authService.signIn(authCredentialsDto);
}
// jwt.strategy를 다른곳에서도 사용할 수 있도록 @Injectable()
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
) {
super({
secretOrKey: 'Secret1234', // 토큰 유효성 체크할 때 쓰는 secret text
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // auth header에서 토큰타입이 bearerToken인 토큰을 추출했다.
});
}
// 위에서 토큰이 유효한지 체크되면 validate 메소드에서 payload에 있는 유저이름이 데이터베이스에서 있는 유저인지 확인후 있다면 유저객체를 return 해준다.
// return 값은 @UseGuards(AuthGuard())를 이용한 모든 요청의 Request Object에 들어간다.
async validate(payload) {
const { username } = payload;
const user: User = await this.userRepository.findOne({
where: { username },
});
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
모듈 'passport-jwt'의 Strategy의 생성자에 포함된
secretOrKey와jwtFromRequest의 값을 상속받아 입력해준다. secretOrKey에 입력된 secret text을 통해 토큰 유효성을 체크하고 jwtFromRequest에는 헤더에서 토큰타입이 bearerToken인 토큰을 추출한다. 토큰이 유효한 경우, validate 메소드가 실행된다. validate는 유효한 토큰의 payload를 받아와서 해당 정보를 사용하여 사용자를 조회하고, 조회된 사용자 객체를 반환한다. 반환된 사용자 객체는 @UseGuards(AuthGuard())를 이용한 모든 요청의 Request Object에 들어간다. 실행 시점은 Passport의 AuthGuard에서 관리된다. @UseGuards(AuthGuard())를 사용하는 라우터나 컨트롤러 메소드에서 해당 전략을 사용하고자 할 때 Passport가 JwtStrategy를 호출하고 유효성 검사를 수행하게 된다. 실패 시에는 Passport에서 자동으로 Unauthorized 예외를 발생시키게 되고, 해당 예외는 Express 미들웨어에서 처리할 수 있다.
auth.module.ts에 추가
JwtStrategy 등록JwtStrategy, PassportModule 등록controller
@Post('/authTest')
@UseGuards(AuthGuard()) //@UseGuards 안에 @nestjs/passport에서 가져온 AuthGuard()를 이용하면 요청안에 유저 정보를 넣어줄 수 있다.
authTest(@Req() req) {
console.log(req.user); //req.user: 유저객체
}
import { ExecutionContext, createParamDecorator } from '@nestjs/common';
import { User } from './user.entity';
export const GetUser = createParamDecorator(
(data, ctx: ExecutionContext): User => {
const req = ctx.switchToHttp().getRequest();
return req.user;
},
);
@Post('/authTest')
@UseGuards(AuthGuard())
test(@GetUser() user: User) {
console.log('user: ', user);
}
@Module({
imports: [TypeOrmModule.forFeature([BoardRepository]), AuthModule],
controllers: [BoardsController],
providers: [BoardsService, BoardRepository],
})
export class BoardsModule {}@Controller('boards')
@UseGuards(AuthGuard())