* 의존성 주입
- authModule에서 import => DI 컨테이너에 올라감
@Module({
imports:[
JwtModule.register({}),
],
controllers: [AuthController],
providers: [AuthService],
})
export class AuthModule {}
- 서비스에서 생성자 주입받고 사용할수 있음.
@Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService
) {
}
* jwt 의사코드
/**
* 1) register with email
* - email, nickname, password 입력받고 사용자 생성
* - 완료되면, accessToken과 refreshToken을 반환
* => 회원가입 후 다시 로그인 방지
*
* 2) loginWithEmail
* - email, password를 입력하면 사용자 검증을 진행한다.
* - 검증이 완료되면 accessToken과 refreshToken을 반환한다
*
* 3) loginUser
* - (1)과 (2)에서 필요한 acessToken, refreshToken을 반환
*
* 4) signToken
* - (3)에서 필요한 토큰들 sign
*
* 5) authenticateWithEmailAndPassword
* - (2)에서 로그인을 진행할때 필요한 기본적인 검증 진행
* 1. 사용자가 존재하는지 확인 (email)
* 2. 비밀번호가 맞는지 확인
* 3. 모두 통과되면 찾은 사용자 정보 반환
* 4. loginWithEmail에서 반환된 데이터를 기반으로 토큰 생성
*/
* 토큰 sign 함수
/**
* Payload(실제 데이터)에 들어갈 정보
*
* 1) email
* 2) sub == 사용자의 id
* 3) type : access토큰인지, refresh 토큰인지
*
* Pick문법 : 가독성이 좋음 // email:string, id: string과 기능은 동일
*/
signToken(user: Pick<UsersModel, 'email' | 'id'>, isRefreshToken: boolean){
const payload = {
email: user.email,
sub: user.id,
type: isRefreshToken ? 'refresh' : 'access',
};
return this.jwtService.sign(payload, {
secret: 'sample',
expiresIn: isRefreshToken? 3600 : 300,
});
}
* authenticationWithEmailAndPassword 구현'
- findUserByEmail 함수필요
async getUserByEmail(email: string){
await this.usersRepository.findOne({
where:{
email,
}
})
}
- 유저 서비스를 auth 서비스에서 사용해야함.
- 임포트, 익스포트, 생성자 주입 다해야함
- import시 모듈을 임포트해야함!! // 모듈을 export했으니 당연함
@Module({
imports:[
JwtModule.register({}),
UsersService,
],
controllers: [AuthController],
providers: [AuthService],
})
export class AuthModule {}
@Module({
imports:[
TypeOrmModule.forFeature([UsersModel]),
],
exports:[
UsersService
],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
@Injectable()
export class AuthService {
constructor(
private readonly jwtService: JwtService,
private readonly usersService: UsersService,
) {}
* registerWithEmail 구현
- user service > create시 중복확인 추가
async createUser(user: Pick<UsersModel, 'email'|'nickname'|'password'>) {
/**
* 중복확인
*/
const nicknameExists = await this.usersRepository.exists({
where: {
nickname: user.nickname,
}
});
if(nicknameExists){
throw new BadRequestException('이미 존재하는 nickname 입니다.');
}
const emailExists = await this.usersRepository.exists({
where: {
email: user.email,
}
});
if(emailExists){
throw new BadRequestException('이미 존재하는 email 입니다.');
}
- auth service
async registerWithEmail(user: Pick<UsersModel, 'nickname'| 'email'| 'password'>){
const hash = await bcrypt.hash( //salt는 자동생성됨
user.password,
HASH_ROUNDS,
)
const newUser = await this.usersService.createUser(user);
return this.loginUser(newUser);
}
* 컨트롤러 구현
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('/login/email')
loginEmail(
@Body('email')email :string,
@Body('password')password : string,){
return this.authService.loginWithEmail({
email,
password,
});
}
@Post('/register/email')
registerEmail(
@Body('nickname')nickname :string,
@Body('email')email :string,
@Body('password')password : string,){
return this.authService.registerWithEmail({
nickname,
email,
password,
});
}
* postman으로 테스트
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImJpc3VAbmF2ZXIuY29tIiwic3ViIjoyLCJ0eXBlIjoiYWNjZXNzIiwiaWF0IjoxNzI2NjQzOTY3LCJleHAiOjE3MjY2NDQyNjd9._3Xj4JAYtRcFXqgBPZRUmNHUq6l7CnFDstKO00pSz6k",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImJpc3VAbmF2ZXIuY29tIiwic3ViIjoyLCJ0eXBlIjoicmVmcmVzaCIsImlhdCI6MTcyNjY0Mzk2NywiZXhwIjoxNzI2NjQ3NTY3fQ.JZmeT4HxD1WY2EsCvQFCFjqkipxZfWnRY0i3MKm-qBc"
}
* 디버그
- 문제 : 비밀번호 맞게 입력했는데, 안됨
- 원인 : await로 결과를 기다려야함
async authenticationWithEmailAndPassword(user: Pick<UsersModel, 'email' | 'password'>){
const existingUser = await this.usersService.getUserByEmail(user.email);
if(!existingUser){
throw new UnauthorizedException('존재하지 않는 사용자 입니다.');
}
const passOk = await bcrypt.compare(user.password, existingUser.password);
- 문제 : 그래도 미인증 사용자
- 원인 : 123123\n도 안됨. 순수 123123만 있어야함
'JS > Nest.js' 카테고리의 다른 글
[Nest] Jwt 토큰 재발급 구현 (0) | 2024.09.18 |
---|---|
[Nest] base64 토큰 인증 구현 (0) | 2024.09.18 |
[Nest] Relation 생성, 1대다, 다대1 연관관계 구현 (0) | 2024.09.18 |
[Nest] typeorm 설정, 리포지토리 설정방법 (0) | 2024.09.18 |
[Nest] enum => 값 제한 하기 (0) | 2024.09.18 |