API 서비스를 제공하는 입장이 되어보면 클라이언트가 서버의 데이터를 가져갈 수 있게 해야하는 만큼 별도의 인증 과정이 필요하다.
JWT는 JSON Web Token의 약어로 JSON 형식의 데이터를 저장하는 토큰이다. JWT는 다음과 같이 세 부분으로 구성되어 있다
- 헤더(HEADER) : 토큰 종류와 해시 알고리즘 정보가 들어 있다.
- 페이로드(PAYLOAD) : 토큰의 내용물이 인코딩된 부분이다.
- 시그니처(SIGNATURE) : 일련의 문자열로, 시그니처를 통해 토큰이 변조되었는지 여부를 확인할 수 있다.
시그니처는 JWT 비밀 키로 만들어진다. 이 비밀키가 노출되면 JWT 토큰을 위조할 수 있으므로 비밀 키를 철저히 숨겨야 한다. 시그니처 자체는 숨기지 않아도 된다.
JWT 토큰은 JWT 비밀 키를 알지 않는 이상 변조가 불가능하다. 변조한 토큰은 시그니처를 비밀 키를 통해 검사할 때 들통난다. 변조할 수 없으므로 내용물이 바뀌지 않았는지 걱정할 필요가 없다. 다시 말하면 내용물을 믿고 사용할 수 있게 된다.
단. 내용물이 외부에 노출되어도 좋은 정보에 한해서이다.
사용자의
이메일이나 권한
같은 것은 ❌
사용자의패스워드
,민감정보
는 ⭕
JWT 토큰의 단점은 용량이 크다는 것이다. 내용물이 들어 있으므로 랜덤 토큰을 사용할 때 보다 용량이 클 수 밖에 없다. 요청 때마다 토큰이 오가서 데이터양이 증가한다.
문자열을 사용해서 매번 사용자 정보를 조회하는 작업의 비용이 더 큰지, 내용물이 들어 있는 JWT토큰을 사용해서 발생하는 데이터 비용이 더 큰지 비교하면 된다.
//npm
$ npm i jsonwebtoken
//yarn
$ yarn add jsonwebtoken
const jwt = require('jsonwebtoken')
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({ extended: false });
// jwt를 이용해서 암호화
const token = jwt.sign(
{ myPayloadDate : 1234 }, // jwt를 이용해서 payload에 설정하는 부분
'mysecretkey',
{ expireIn : '10s' }
);
console.log('암호화 =>', token)
// jwt를 이용해서 비밀키 복호화
const decodeToken = jwt.decode(token);
console.log('복호화 =>', decodeToken);
// 1. jwt를 이용해서 변조 데이터 검증
// 2. 해당하는 jwt가 만료되었는지 검증
const decodedValueVerify = jwt.verify(token, 'mysecretkey');
console.log('검증 =>', decodedValueVerify);
암호화 => eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTk0MTIyNzMsImV4cCI6MTY5OTQxMjMyN30.
dKjPDd5l8II8zEom021eoJFU_UjI_ssdUPBN79zSTfQ
복호화 => { myPayloadData: 1234, iat: 1699412273, exp: 1699412327 }
검증 => { myPayloadData: 1234, iat: 1699412273, exp: 1699412327 }
잘썼구먼유~.~