userId=user-1321;userName=sparta
와 같이 문자열 형식으로 존재하며 쿠키 간에는 세미콜론(;)
으로 구분.header.payload.signature
의 형식으로 3가지의 데이터를 포함. (개미처럼 머리, 가슴, 배).
이 포함된 데이터여야 한다.https://jwt.io/ 에서 간단히 확인 가능하다.
데이터를 교환하고 관리하는 방식인 쿠키/세션과 달리, JWT는 단순히 데이터를 표현하는 형식임
JWT로 만든 데이터를 브라우저로 보내도 쿠키처럼 자동으로 저장되지는 않지만, 변조가 거의 불가능하고 서버에 데이터를 저장하지 않기 때문에 서버를 Stateless(무상태)로 관리할 수 있다. 그래서 요즘 많이 쓰인다.
Stateless(무상태)와 Stateful(상태 보존)의 차이를 간단히 설명하자면,
Node.js 서버가 언제든 죽었다 살아나도 똑같은 동작을 하면 Stateless
반대로 서버가 죽었다 살아났을때 조금이라도 동작이 다른 경우 Stateful
즉, 서버가 스스로 어떤 기억을 갖고 다른 결정을 하냐 마냐의 차이라고 보면 더 쉽다.
로그인 정보를 서버에 저장하게 되면 무조건 Stateful(상태 보존)이라고 볼 수 있다.
npm init
npm i jsonwebtoken -S
설치해주자.
그리고 검증
검증을 하는 이유는
1. 암호화를 할 때 사용한 비밀키가 일치하는지 확인할려고
2. 해당하는 jwt가 만료되었는지 확인할려고
-- + 만료시간 코드에 추가해주자
놀이공원에 비유해볼까?
Access Token은 사용자의 권한이 확인(ex: 로그인) 되었을 경우 해당 사용자를 인증하는 용도로 발급
이전에 발급한 jwt또한 Access Token이라고 부를 수 있다.
사용자가 Access Token을 가지고 인증을 요청할 경우 Token을 생성할 때
사용한 비밀키(Secret Key)를 가지고 인증하기 때문에, 복잡한 설계없이 코드를 구현할 수 있고, 여러 분기를 거치지 않아도 된다는 장점 존재.
Stateless(무상태) 즉, jwt를 이용해 사용자의 인증 여부는 확인할 수 있지만,
처음 발급한 사용자 본인인지 확인할 수는 없다.
Access Token은 그 자체로도 사용자를 인증하는 모든 정보를 가지고 있다.
그렇기 때문에 탈취 당했을 때 피해 막심...
Refresh Token은 Access Token 처럼 해당하는 사용자의 모든 인증 정보를
관리하는 것이 아닌, 특정한 사용자가 Access Token을 발급받을 수 있게 하기
위한 용도로만 사용
Refesh Token은 사용자의 인증정보를 사용자가 가지고 있는 것이 아닌, 서버에서 해당 사용자의 정보를 저장소 또는 별도의 DB에 저장하여 관리.
그렇기 때문에, 서버에서 특정 Token 만료가 필요할 경우 저장된 Token을 제거하여 사용자의 인증 여부를 언제든지 제어가 가능.
그럼 왜 바로 Access Token을 발급하지 않고, Refresh Token을 거쳐서 Access Token을 발급함?
사용자에게 발급한 Token이 탈취당할 경우 피해를 최소화 하기 위해서 사용
실제 사용하는 OTP와 같이 짧은 시간 내에서만 인증 정보를 사용할 수 있게하고,
주기적으로 재발급하여, 토큰이 유출되더라도 오랜 기간동안 피해를 입는것이 아닌,
짧은 기간동안만 사용가능하도록 하여 피해를 최소화.
먼저 셋팅부터
npm init -y
npm install express jsonwebtoken cookie-parser -S
설치해주고
// app.js
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const express = require("express");
const app = express();
const port = 3002;
const SECRET_KEY = `HangHae99`;
app.use(cookieParser());
app.get("/", (req, res) => {
res.status(200).send("Hello Token!");
})
app.listen(port, () => {
console.log(port, '포트로 서버가 열렸어요!');
})
연결 잘 됐나 확인해주고 스타트
사용자가 GET /set-token/:id API를 호출했을때 Access Token과 Refresh Token을 2개 발급하게 되고, Refresh Token을 Key 값으로 입력된 id를 찾을 수 있게 구현
그리고 accessToken, refreshToken이라는 Key로 Cookie를 2개 발급
왜 인증되었다는 메세지가 아닌 새롭게 발급되었다는 메세지가 응답한걸까?
이유는 Access Token을 생성할 때, 10초의 만료기간을 설정하였고(30번째 줄)
토큰을 확인하기까지 10초이상의 시간을 소모했기 때문.
그럼 빠르게 Send를 2번눌러서 정상적으로 메세지가 호출되는걸 확인해볼까?
GET /set-token/:id API에서 84의 Payload를 가진 Token을 만들었던 정보를 확인
굿..
Access Token과 Refresh Token을 비교했을 때, 프로젝트를 빠르게 구현해야하거나 사용자의 요청에 대한 인증을 최소화 하기 위해서는 Access Token을 사용
보안성을 중요시 여기고, 서버를 좀더 탄탄하게 구성해야 할 경우에는 Refesh Token을 사용