Study/NestJS

NestJS JWT 오류 해결 secretOrPrivateKey must have a value

isjiji 2023. 6. 16. 16:59

검색과 chat GPT를 사용하여 찾을 수 있는 방식은 다 적용해보았지만 아무리해도 문제해결이 안됐다. 

그러다 최종적으로 해결하게되어 기록으로 남겨 공유한다. 

 

 

 

오류 :

secretOrPrivateKey must have a value
C:\test\awasxr20230615\test-probuf2_interceptor\node_modules\jsonwebtoken\sign.js:105
    return failure(new Error('secretOrPrivateKey must have a value'));
                   ^
Error: secretOrPrivateKey must have a value
    at Object.module.exports [as sign] (C:\test\awasxr20230615\test-probuf2_interceptor\node_modules\jsonwebtoken\sign.js:105:20)
    at JwtService.sign (C:\test\awasxr20230615\test-probuf2_interceptor\node_modules\@nestjs\jwt\dist\jwt.service.js:28:20)
    at AuthService.jwtLogIn (C:\test\awasxr20230615\test-probuf2_interceptor\src\auth\auth.service.ts:51:48)
    at ConnsocketController.serviceAccessHandler (C:\test\awasxr20230615\test-probuf2_interceptor\src\common\connsocket\connsocket.controller.ts:438:40)
    at ConnsocketController.<anonymous> (C:\test\awasxr20230615\test-probuf2_interceptor\src\common\connsocket\connsocket.controller.ts:220:33)

토큰생성하는 부분에서 secret key를 찾지못하는 오류 발생

 

 

 

해결방법

 

1. JwtModule.registerAsync
node.js의 비동기화로 인해 .env파일을 읽지 못하는 것일 경우 auth.module에서 async, await 설정을 해준다.

기존의 코드는 JwtModule.register를 사용하였고 process.env.JWT_SECRET .env파일의 시크릿키를 불렀다. 여기서, .env 파일이 빌드되지 않았을 수도 있다고 판단하여 Config 라이브러리를 설치하고 ConfigService를 이용하여 .env 파일을 미리 로드하게 만들었으며 async, await 설정을 해주었다.

그리고 app.module.ts에 설정을 .env 설정을 해둔다.

//이전 소스코드 
 JwtModule.register({
       secret:
         process.env.JWT_SECRET,
       signOptions: { expiresIn: '1y' },
     }),
//수정된 소스코드
    JwtModule.registerAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        secret:secretOrPrivateKey: config.get<string>('JWT_SECRET'),
        signOptions: { expiresIn: '1y' },
      }),
    }),
//app.module.ts 소스코드
    ConfigModule.forRoot({
      load: [configuration],
      envFilePath: ['.env'],
      isGlobal: true,
    }),

 

 

2. dotenv 라이브러리 이용

import * as dotenv from 'dotenv';

.env 파일을 로드하고 사용가능하게 만들기 위해 dotenv라이브러리를 설치하고 main.ts 의 첫줄에서 dotenv.config() 메서드를 실행시킨다.

import * as dotenv from 'dotenv';

async function bootstrap() {
  dotenv.config();

jwt.JwtSrategy.ts 에도 동일하게 적용한다.

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    @InjectRepository(UserData)
    private userRepository: Repository<UserData>,
    private configService: ConfigService,
  ) {
    dotenv.config();
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get<string>('JWT_SECRET'),
      ignoreExpiration: false,
    });
  }

 

 

3. jwtService.signAsync() 사용하기

sign함수가 비동기방식인것을 고려하여 JWTService에서 제공하는 signAsync함수를 적용하였다.

//기존코드
    return {
      status: 1,
      tocken: this.jwtService.sign(payload),
    }; 
//수정코드
    return {
      status: 1,
      tocken: await this.jwtService.signAsync(payload, {
        secret: process.env.JWT_SECRET,
      }),
    };

 

 

4. jwtService.signAsync() 인자에 옵션을 추가한다. //성공방식

auth.service.ts의 토큰생성하는 로직 전에 console.log('jwtService', this.jwtService); 로그를 찍었더니 아래와 같이 나왔다. option이 비어있는것이다. option이 할당되지 않은 것은 알았지만, 어떻게 할당해야하는지가 미지수였는데, 로그를 찍어보니 option : {}, 즉 JSON 형식이었다. 인자에 JSON을 만들고 secret : process.env.JWT_SECRET 을 추가했더니 작동되었다.

jwtSErvice JwtService {
  options: {},
  logger: Logger { context: 'JwtService', options: {} }
}
    const payload = { name: member.userName, sub: member.userId };
    
    return {
      status: 1,
      tocken: await this.jwtService.signAsync(payload, {
        secret: process.env.JWT_SECRET,
      }),
    }; 

 

 

느낀점 : 오류가 발생하면 늘 오류구문을 구글링하여 누군가 제공해주는 해결법을 찾으려고만했다. 그런데 아무리 검색하고 챗지피티에도 물어보았지만 에러 상태는 동일해도 해결방법이 맞는게 없었다. 그러다 동료분께 SOS를 쳤는데, 동료분들이 디버깅해봤냐고 물어봤다. 디버깅.. 하긴 했으나 '이게 맞나? 이방법이 맞나?' 고민하는 수준으로 애매하게 디버깅을 했었고, 동료분이 디버깅하는것을 눈으로 익혀서 덕분에 거의 처음으로  console.log()가 아닌 제대로된 디버깅으로 라이브러리 소스코드들을 검사하면서 어떤 이유때문에, 어디서 에러가 나는지 추측할 수 있었다. 디버깅전에는 가림막에 가려진채로 문제를 찾는 것 같았는데 디버깅을 하면서는 앞이 선명하게 보이는 상태로 문제를 찾는 것 같았다. 

그 덕에 예상되는 에러 발생하는 지점을 중점적으로 고민하다가 문제를 해결할 수 있었다. 동료분들에게도 너무 감사하고 내스스로가 한층 더 성장할 수 있어서 만족스럽다.