일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- ...args
- .toLocalString()
- 1주차
- 2020년 준비
- 2주차
- 4주차
- 5주차
- array
- array method
- async
- authentication
- AWS
- codestates
- commit
- Cookie
- CSS
- Data Structre
- Data Structure
- DataSturcutre
- Date.now()
- DB에 사진 저장하기
- Dev log
- DOM
- EC2
- EC2로 웹 만드는 방법
- EC2와 S3 연결하기
- element
- Es5
- ES6
- event 객체
- Today
- Total
souvenir
로컬 로그인 구현_JWT 본문
이 내용은 20.10-20.11 중 notion으로 진행되었던 내용을 정리 차원에서 다시 작성하는 블로그 글입니다.
출처 : https://bit.ly/2IoLe5C
한 주동안은 아이디어를 기반으로 세부 내용을 정리하고 문서화하였다.
해당 내용은 팀 notion에도 정리하였지만 github wiki에도 추가하였다.bit.ly/35dkJJG
로컬 로그인 구현
이번에는 백엔드 담당으로서 로컬 로그인을 구현을 맡았다.
JWT를 이용해서 Access token-Refresh token 인증 로직을 만드는 것이 우리의 계획이었다. 토큰 기반 인증에 대한 문서는 많았지만 Access token-Refresh token 로직을 구현하는 것을 설명하는 글을 흔치 않았다. 심지어 어떤 블로그 글은 저자와 댓글 단 사람이 전혀 다른 주장을 펼치기도 해 혼란을 빚었다.
출처 : https://medium.com/neillab/what-is-jwt-89889759ae37
로직에 앞서 JWT 자체에 대한 이해를 해보기로 하였다.
JWT란?
사실 이에 대해서는 내 글도 좋지만 정보성을 원하는 사람은 ttps://tansfil.tistory.com/59?category=255594
위 글을 참고하길 바란다. JWT 뿐 아니라 대중적으로 사용하는 인증 로직은 자세하게 설명해주셔서 초반에 이해하는데 큰 도움이 되었다.
위 글을 읽지 않은 사람을 위해 정리해보자면 JWT란
JSON Web Token으로서 token을 JSON 형식으로 만들어 제공하는 것을 의미한다.
HEADER.PAYLOAD.VERIFY SIGNATURE
형태로서 header에는 암호화 방식을, payload에는 유저정보(email, 유저 이름 등 자유롭게 설정 가능), signature에는 말 그대로 서명 부분으로 발행자, 만료기간 등을 설정하여 암호화된 부분이다. 실제로 decoding이나 유효성 검사를 할 때 이 signature 부분을 확인하게 된다. JWT를 만드는 방법은 생각보다 간단한데, npm 홈페이지의 JWT 모듈 화면에 잘 설명되어 있다. 아래 함수가 바로 JWT 함수를 생성하는 함수이다.
참고 : www.npmjs.com/package/jsonwebtoken#token-expiration-exp-claim
jwt.sign(payload, secretOrPrivateKey, [options, callback])
callback을 사용하면 비동적으로, 사용하지 않으면 동기적을 JWT가 생성된다. 이 동기/비동기에 대해서도 할 말이 많지만 나중에 정리해서 올리도록 하고, 일단 여기서는 JWT를 어떻게 만드는지만 예시를 들어 설명하고자 한다.
jwt.sign(
{ account: email, gmt: Date.now() },
process.env.ACCESS_SECRET,
{
expiresIn: '100m',
issuer: 'nyam-nyamServer',
})
jwt.sign에서 첫번째 인자는 payload를 넣어준다. 우리 프로젝트에서는 email를 기준으로 유저 정보를 확인하고자 하였기 때문에 accout라는 키에 클라이언트 측에서 요청한 email와 생성일자를 합쳐 payload를 구성하였다. 두번째 인자는 암호화를 위해 secreat 키를 따로 설정한 것이다. 이는 외부에 유출되면 안되므로 .env 파일에서 설정해주었다. 마지막으로 option에서 만료기간은 100분으로 설정하고 발행자를 설정해주었다.
위 내용을 decode 해주면 아래와 같이 나온다.
const decoded = jwt.decode(access_token, { complete: true }); // decode 하는 함수
const account = decoded.payload;
consoe.log(account) // { account : email, gmt : 발행일자 }
그러나 decode 함수는 유효성 검사를 목적으로 사용해서는 안된다.
서명 부분을 점검하는 것이 아닌 단순히 payload 부분을 확인하는 것이 목적이기 때문이다. 대신 정확한 함수는 아래와 같다
jwt.verify(token, secretOrPublicKey, [options, callback])
위 함수는 jwt.sign 함수와 매우 유사하다. 옵션으로 들어가는 키들도 거의 똑같은 것 같다.
이 함수를 사용하면 signature 부분과 만료기간을 확인해서 유효한지 error 메세지를 내주는 함수이다. 아래와 같이 사용할 수 있다.
jwt.verify(
access_token, // 클라이언트 측에서 받은 access token
process.env.ACCESS_SECRET, // .env에서 설정한 secret
{
expiresIn: '100m',
issuer: 'nyam-nyamServer',
},
(err, decode) => { //callback을 이렇게 설정하면 비동기적으로 운영
if (err) {
reject(err);
} else {
resolve(decode); // 이상이 없으면 기존 access token과 함께 응답으로 보냄
return res.status(200).json({
message: 'access 문제없음',
access_token: access_token,
})
.catch(err => console.log(err)); //{ message : 오류 내용 }
위와 같이 유효성 검사를 했을 때 나오는 오류는 아래와 같이 세 가지이다.
1. TokenExpiredError : 만료 오류
error.mssage 로는 'jwt expired' 라고 출력된다.
2.. JsonWebTokenError : 기타 서명 오류
error,message 로는 서명이 유효하지 않다던지, 수정되었다는 메세지가 출력된다.
3. NotBeforeError : jwt가 아닌 경우
error.message 로 'jwt not active' 가 출력된다.
이 기본 내용만 알면 JWT 생성과 관리 자체는 그리 어렵지 않다.
그렇지만 이 외의 복병이 있었는데 JWT를 이용한 Access token-Refresh token 인증 로직 구현 과정 중 어려움을 겪었던 부분은 다음 글에서 소개하고자 한다.
'2020년 > Final-Project' 카테고리의 다른 글
multer-S3 사용기 (0) | 2020.11.27 |
---|---|
Final-Project 기획 및 준비 (0) | 2020.11.10 |