JWT에 대한 배경지식이 전혀 없으니 Nest.js 공식 Docs를 뒤져보고 해봐도 전혀 로직이 이해되지 않았어서 정말 힘들었었다. 기존 토이 프로젝트에서는 그냥 쿠키 & 세션으로 끝냈었는데 JWT는 처음인데다가 심지어 Nest.js도 처음이어서 뭐가 뭔지 전혀 몰랐다. 그래도 약 6시간의 시행착오 끝에 로그인을 구현해냈다!!!
정말 이렇게 고생했는데 까먹어버리면 너무 억울할 것 같아서 블로그에 기록을 남긴다..
기억하기 위해 기록한다... 정말 명언인 것 같다.
기존의 쿠키-세션 기반 인증 방식은 메모리를 사용했었다.
하지만 토큰 기반 인증 방식은 사용자에게 토큰을 발급한 뒤, 이를 서버에 보낼 때 헤더에 토큰을 같이 보내어 유효성 검사를 하는 방식으로 진행된다. 즉, STATELESS한 특징을 가진다!
Json을 사용하여 사용자에 대한 속성을 저장하는 claim 기반 Web token
토큰 자체를 정보로 사용하는 self-contained 방식 사용
https://mangkyu.tistory.com/56
Header
JWT를 검증하는데 필요한 정보를 가진 JSON을 Base64 알고리즘 기반으로 인코딩한 문자열,
검증을 하기위한 내용 가지고 있음!
Payload
JWT에 저장 된 값
Payload의 값은 암호화되지 않기에, 비밀번호와 같은 민감한 값을 넣으면 안됨!
Signature
JWT를 인코딩하거나 유효성 검증을 할 때 사용하는 암호화 된 코드
flow는 다음과 같다 (아래는 controller)
1. login 함수 수행 전에 UseGuard middleware로 id, pw 검증
2. id, pw가 맞으면 login 함수 수행 -> jwt 발급
3. token 정보와 함께 들어오면 UseGuard middleware로 JWT 검증
4. JWT가 올바르면 함수 실행
따라서 다음과 같은 것들을 정의해줘야만 한다.
1. AuthGuard (local & jwt)
사용할 AuthGuard를 정의해준다.
2. Guard Strategy (LocalStrategy & JwtStrategy)
이 Guard가 수행할 작업을 validate() 함수에 넣어준다
3. Services
"단일 책임 원칙"을 지키기 위해 Service에 validateUser 등을 구현해주자
4. Controllers
컨트롤러에 Authentication을 수행할 위치마다 @UseGuard를 넣어주자!
참고)
어떤 Authentication을 사용하는지에 따라 사용할 passport 내 모듈이 달라진다.
따라서 https://www.passportjs.org/ 를 참고하여 Guard와 Strategy를 정의하자