PassportStrategy-LocalStrategy로 인증할 시 발생하는 401 에러 해결방법

에옹이다아옹·2023년 11월 5일
0
post-thumbnail

혼자서 도전중인 Nest.js로 개발하는 로그인 인증 프로젝트 도중 강의를 따라가다가
@UseAuthGuards(LocalAuthGuards)를 붙이기만 하면 401 에러가 발생해 구글링을 하다 해결방법을 찾아 공유한다

나는 우선 Passport를 활용해 인증을 구현중이었다.

local-strategy.ts

  • 원래 작성한 코드
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
    constructor(private authService: AuthService) {
        super();
    }

    async validate(loginDto:LoginDto) {
        const user = await this.authService.validateUser(loginDto);
        // console.log('validate', user)
        if (!user) {
            throw new UnauthorizedException()
        }
        return user;
    }
}

  • auth.service.ts

	//로그인 함수
	async login(user: LoginDto) {
        const findUser: UserDto = await this.userService.findFields({
            where: {userId: user.userId},
        });

        const payload = {userId: user.userId, sub: {userName: findUser?findUser.name:''}}

        // console.log('payload', payload)
        return {
            ...user,
            accessToken: this.jwtService.sign(payload),
        };
    }

	//유효한 유저인지 판별
    async validateUser(
        loginDto:LoginDto
    ) {
        let userFind: User = await this.userService
            .findFields({
            where: {userId: loginDto.userId},
        });

        //console.log('userFind', userFind)

        const validatePassword = await bcrypt.compare(
            loginDto.password,
            userFind.password,
        );

        if (userFind && validatePassword) {
            const {password, ...result} = userFind
            return result
        }
        return null;
    }
  • auth.controller.ts
    @UseGuards(LocalAuthGuard)
    @Post('/login')
    async login(@Req() req) {
        console.log('req', req.body)
        return await this.authService.login(req.body)
    }

auth.controller에서 '/auth/login'을 호출하면 LocalAuthGuard=>LocalStrategy=>validate()=>AuthService의 validateUser() 순서대로 호출된다

그런데 자꾸

올바른 ID와 PW를 넘겨주는데도 401에러가 났다

구글링을 하다가 답을 찾았는데

결론부터 말하자면 LocalStrategy내에 쓰이는 validate함수 안에는 username, password 이름을 똑같이 일치시켜줘야 동작한다는 것...

편하게 받으려고 LoginDto={userId:string, password:string} 타입을 따로 만들어서 받게 해놨는데 전혀 소용 없었음;;


수정한 코드

  • local-strategy.ts
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
    constructor(private authService: AuthService) {
        super();
    }

    async validate(username:string, password:string) {
        const user = await this.authService.validateUser({username, password});
        if (!user) {
            throw new UnauthorizedException()
        }
        return user;
    }
}

  • auth.service.ts
	async login(user: {username:string, password:string}) {
        const findUser: UserDto = await this.userService.findFields({
            where: {userId: user.username},
        });

        const payload = {userId: user.username, sub: {userName: findUser?findUser.name:''}}

        return {
            ...user,
            accessToken: this.jwtService.sign(payload),
        };
    }

	async validateUser(
        loginDto:{username:string, password:string}
    ) {
        let userFind: User = await this.userService
            .findFields({
            where: {userId: loginDto.username},
        });


        const validatePassword = await bcrypt.compare(
            loginDto.password,
            userFind.password,
        );

        if (userFind && validatePassword) {
            const {password, ...result} = userFind
            return result
        }

        return null;
    }

잘 나온다!!




참고

https://github.com/nestjs/docs.nestjs.com/issues/875

profile
숲(구조)을 보는 개발자

0개의 댓글