현재까지는 username이라는 정해진 것으로 auth 인증 절차를 진행했습니다. 이제는 username 대신 email을 이용한 인증 절차로 변경하려고 합니다.
일단 이전에 추가했던 DB의 데이터를 지우기 위하여 user table을 삭제한 후 진행해주세요.
/src/users/user.entity.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column({ unique: true })
username: string;
@Column()
password: string;
}
이전에 있던 Column들을 많이 삭제 하였습니다. 이제는 사용할 Column을 그때 그때 추가하면서 사용하려고 합니다. 먼저 Auth인증 절차에 사용할 Email를 Column을 만들었습니다.
DB에서 Email 값을 이용하여 User정보를 가져오는 메소드를 만듭니다.
/src/users/users.service.ts
...생략
@Injectable()
export class UsersService {
...생략
async getByEmail(email: string) {
return this.usersRepository.findOne({ email });
}
}
이전 코드에 있던 username 부분을 email로 바꿔주면 검증 부분에서 UserService의 getByEmail 메소드를 호출하여 검증합니다.
/src/auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from 'src/users/user.entity';
import { UsersService } from '../users/users.service';
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
async vaildateUser(email: string, password: string): Promise<any> {
const user = await this.usersService.getByEmail(email);
if (user && user.password === password) {
const { password, ...result } = user;
return result;
}
return null;
}
async login(user: User) {
const payload = { email: user.email, sub: user.id };
const token = this.jwtService.sign(payload);
return token;
}
}
passport는 특정한 매개 변수 세트(username, password)를 사용하여 validate 메소드를 호출합니다. 하지만 현재 username의 역할을 email이 대신 합니다. 새로운 매개 변수 세트가 email, password가 되었습니다.
앞선 코드와 같이 username부분을 email로 수정해줍니다.
/src/auth/strategies/local.strategy.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { User } from 'src/users/user.entity';
import { AuthService } from '../auth.service';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({
usernameField: 'email',
});
}
async validate(email: string, password: string): Promise<User> {
const user = await this.authService.vaildateUser(email, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
새 user를 추가하기 위하여 기존에 막혀있던 createNewUser의 경로를 오픈해줍니다.
/src/users/users.controller.ts
...생략
@Controller('users')
export class UsersController {
...생략
@Public()
@Post()
async createNewUser(@Body() user: User): Promise<void> {
await this.usersService.createNewUser(user);
}
}
Request
[
{
"email": "test1@gmail.com",
"username": "test1",
"password": "qwer1234@"
},
{
"email": "test2@gmail.com",
"username": "test2",
"password": "qwer3333"
}
]
Request
{
"email": "test1@gmail.com",
"password": "qwer1234@"
}
Response
{
"id": 1,
"email": "test1@gmail.com",
"username": "test1",
"password": "qwer1234@"
}
Response
{
"id": 2,
"email": "test2@gmail.com",
"username": "test2",
"password": "qwer3333"
}
Response
{
"statusCode": 401,
"message": "Unauthorized"
}
다음 포스트에서 수정될 사항
정리가 정말 잘되어있네요. 잘보고갑니다~