ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JWT와 로그인 서비스& 순환 참조 모듈
    FrameWork/Nest.js 2022. 7. 3. 15:41

     

     

    1. 요청이 들어온다.

     

    2. Globally bound middleware

    3. Module bound middleware

     

    4.Global guard

    5.Controller guard

    6.Route guard

     

    7. Global intercceptors (pre-controller)

    8. Controller intercceptors (pre-controller)

    9. Route intercceptors (pre-controller)

     

    10. Global pipes

    11. Controller pipes

    12. Route pipes

     

    13.Route parameter pipes

    14.Controller (method handler)

    15.Service(존재한다면)

     

    9. Route intercceptors (post-request)

    8. Controller intercceptors (post-request)

    7. Global intercceptors (post-request)

     

    19 Exception filters (route > controller > global)

     

    20. 서버에서 응답 

     

    글쓰기 API를 rquest한다고 했을때, 동시에 front에는 이미 login을 한 상태여서 JWT가 안전한 공간에 저장 되어 있다. 그럼 글쓰기 API를 보낼 때, header에 jwt를 실어서 보내준다. 그럼 back에서는 그것을 받고 JWT Guard를 통해서 JWT Strategy를 실행해주고 JWT Strategy에서 scret key를 가지고, 디코딩을 한다. 그리고 해당하는 user를 request에 저장을 해준다. 그리고 보내진 user의 정보를 가지고, 글쓰기 API에 로직이 수행이된다.

     

    jwt.guard.ts

    JwtAuthGuard 또한 의존성 주입이 가능한 class이다. 특이하게도 passport의 AuthGuard라는 것을 상속받아 strategy를 자동으로 실행해주는 기능이 있다.

     

    jwt.strategy.ts

    AuthGuard 전략에 대한 내용을 코드로 적어 준다. 

    .fromAuthHeaderAsBearerToken() 헤더의 token으로 부터 jwt를 추출한다는 의미이다. JwtAuthGuard는 JwtStrategy를 자동으로 실행해주고  JwtStrategy는 validate 메서드를 실행해 준다.

     

    request에 jwt가 포함되어 날라 왔을 때, 해당하는 것을 읽고, payload를 뽑아 냈다면, payload에 대해서 유효성 검사를 해주어야 한다.

     

     

    auth.module.ts

    PassportModule.register에서는 나중에 만들게될 strategy에 대해 기본 설정을 해줄수 있다.

    JwtModule.register은 로그인 할 때 사용될 것이다.

     

     

     

    AuthService에서 login 로직을 구현한 다음에 CatController에서 DI를 통해서 return을 해줄 것이다. 즉 CatController에 loin은 AuthModule에 service를 사용하는 것이다.

     

    로그인을 하려면 email과 password가 필요하고, emial이 DB에 존재하는지 check하고, 존재할 경우 request받은 password와 해당하는 회원의 password가 일치하는지 확인한다. 이러한 과정을 겉쳐 유효성 검사가 모두 통과가 되면, return으로 jwt token을 보내 준다.

     

    AuthServiece에서 DI된 객체 castRepository: CatsRepository를 사용하려면 AuthModule의 @Module 데코레이터에  providers로 CatsRepository를 등록해주어야 한다.

     

     

    @Module exports와 imports

    jwt.strategy.ts

    위 메서드에서 front에서 저장되 JWT가 날라왔을 때 해당하는 것을 읽고 거기서, payload를 읽어 냈다면, payload에서 유효성 검증을 해주어야한다. 그 code를 메서드 안에 정의한다.

     

     

     

    위와  코드와 같이 CatModule 자체를 imports 해주어도 괜찮은데, 그럼 CatModule @Module 데코레이터에서 exports한 것을 사용할 수 있다.

     

    auth.service.ts

    .findOne 이라는 catModel안에있는 메서드를 사용해서 인자로 받은 email과 인자에서 받은 email을 비교해서, Cat 객체를 가져와서 반환한다.

     

     

    auth.service.ts

    그렇게 받아온 cat을 return 받는데 cat이 없다면, 가입한적 없는 email이므로 excepion을 반환한다.

     

    bcrypt안에 .compare라는 메서드가 있다. 그 메서드 안에서 request로 받아온 password와 catsRepository를 통해 반환 받은 cat 객체의 password인 cat.password와 비교를 해준다.

     

    .password를 bcrypt를 통해서 함수화 되어있기 때문에 반드시 bcrypt의 .compare() 메서드를 활용해서 비교해주어야 한다. 그리고 해당 함수는 Promise를 return하기 때문에 await를 붙여야 한다.

     

    위 과정을 겉쳐서 유효성 검사가 끝났으면, jwt를 반환해야 한다.

     

    jwt를 반환하려면 nestjwt에 존재하는 jwt service를 사용해야 한다.

    위 와 같이 constructor를 사용해서 jwtService:JwtSevice를 DI받아야 한다. 이  jwtService:JwtSevice는 AuthModule의  JwtModule에서 제공해주는 공급자(provider,service)인 것이다. 

     

    jwtService를 이용해서 jwt를 생성하고 이를 front에 return해준다.

     

    *jwt(Json Web token)

    Header : base64 인코딩 토큰의 타입과 알고리즘

    Payload : base64 인코딩 데이터 (key-value)

    Signature : Header/Payload를 조합하고 비밀키로 서명한 후, base64로 인코딩

     

    Header같은 경우도 환경 setting으로 처리가 되어 있고, 알고리즘도 default값으로 nestjwt에 저장이되어 있다.

    Signatur의 비밀키는 auth.module.ts @Module 데코레이터에서 JwtModule.rgister()메소드의 속성으로 등록한 secret을 의한다.

     

     

    payload에 담기는 객체에서 sub는 toke 제목을 의미한다.  거기에 cat의 고유 식별자인 cat.id넣는다. 이렇게 payload를 만들었으면, jwtServie에 .sing이하는 함수에 payload를 파라미터로 넣어 토큰을 만들어 낸다.

     

    순환 모듈 참조 문제 해결

    CatsModule
    AuthModule

    CatsModule과 AuthModule이 서로를 import하고 있다.

    => 

    모듈 전달 참조

    모듈 간의 순화 종속성을 해결 forwardRef()하려면 모듈 연관의 양쪽에서 동일한 유틸리티 함수를 사용해야한다.

    @Injectable()
    export class CatsService {
      constructor(
        @Inject(forwardRef(() => CommonService))
        private commonService: CommonService,
      ) {}
    }

     

    jwt.strategy.ts

    => 이미 front에서 가지고있는 token을 디코딩해서 확인할 때 쓰인다.

     

    auth.module.ts 

    => JwtModule은 jwt를 만들어 주는 역할을 한다.

     

    정리 

    1.AuathGuard를 extends한 JwtAuthGuard class가 존재한다.

    2.특정 controller에서 특정 메소드에서 @UseGuards() 데코레이터를 통해서 JwtAuthGuard class를 불러오면

    3.PassportStrategy를 extends 한 JwtStrategy class의 validate 메서드가 실행되면서 

    4. @UseGuards() 데코레이터를 통해서 JwtAuthGuard  불러오고 있는 메서드에 Request 타입의 인자로 인증정보를 해당 메서드에 전해준다.

     

     

     

     

    [출처-https://www.inflearn.com/course/%ED%83%84%ED%83%84%ED%95%9C-%EB%B0%B1%EC%97%94%EB%93%9C-%EB%84%A4%EC%8A%A4%ED%8A%B8/dashboard]

    댓글

Designed by Tistory.