1. Access Token
(1) 이용자가 로그인 시도
(2) 서버에서 이용자를 확인하고 입장권 (토큰)발급 하는데 JWT토큰 인증정보를 payload에 할당하고 생성
(3) 생성한 토큰을 클라이언트에 반환해주고 클라이언트가 이 토큰을 가지고 있는다.
(4) 클라이언트에서 권한을 인증 요청할때 이 토큰을 같이 보낸다.
(5) 서버는 토큰을 확인하고 payload의 인코딩되어 있는 값을 디코딩해서 사용자의 권한을 확인하고
(입장권이 맞는지) 데이터를 반환한다.
(6) 만약에 토큰이 정상적인지 확인하고 (토큰이 썩었는지 입장권 시간이 지났는지)
(7) 날짜가 지난 토큰이면 새로 로그인 시킨다. 토큰 재발급
2. Refresh Token
Access token만 쓰면 인증보안에 취약할수 있고 다른사람이 악의적으로 토큰을 취득하면 토큰의 유효기간이
끝나기 전까지는 막을수 없다. (이미 입장권 보여주고 입장함)
Access token의 유효기간을 짧게 하고 유효기간이 짧으니까 로그인을 자주 해야하는 문제가 생기는데
이는 사용자가 이용하기 힘들다.
그부분을 Refresh token으로 해결할수 있다.
Refresh token과 Access token은 둘다 JWT토큰이고 Refresh token은 유효기간을 길게주고 Access token이 유효기간이 끝났을때 발급해주는 역할만 한다.
보통 Access token의 유효기간을 30분만 주면 Refresh token의 유효기간을 하루 주고 Access token의 유효기간이 끝나면
Refresh token의 유효기간을 확인하고 Access token을 재발급 해준다.
3. Access token과 Refresh token
(1) 이용자가 로그인
(2) 서버에서 사용자를 확인하고 입장권 권한 인증 정보를 payload에 할당해서 생성
(3) Refresh token도 생성해서 서버에 저장하고 두 토큰 모두 클라이언트에 반환한다.
(4) 클라이언트도 두 토큰을 모두 저장한다.
(5) 클라이언트가 권한인증이 필요해서 요청하면 Access token을 전달해서 요청한다.
(6) 서버는 전달받은 토큰을 확인하고 payload의 인코딩된 값을 디코딩해서 사용자의 권한을 확인한다.
(7) 토큰이 정상적인지 확인을 한다.
(8) 날짜가 지난 토큰이면 새로 로그인 시켜서 토큰을 발급받게 한다.
(9) 서버는 Access token과 Refresh token을 확인하고 Refresh token이 만료되지 않았으며
새로운 Access token을 발급해서 클라이언트에 전달한다.
4. Access token의 유효기간이 짧은 이유
해커가 악의적으로 access token을 얻었을때 로그인이 이미 되어있는 상태라 막기가 힘들다.
그렇기 때문에 access token의 유효기간을 짧게 하고 refresh token의 유효기간을 길게해서
refresh token을 다시 확인시켜서 사용자가 로그인을 자주하는 불편함을 보완해준다.
또한 refresh token으로 악의적으로 탈취된 access token을 갱신해주는 역할도 해준다.
5. 해보기
const express = require("express");
//서버 객체 생성
const app = express();
const dot = require("dotenv");
const cookie = require("cookie-parser");
const jwt = require("jsonwebtoken");
const fs = require("fs");
// .env파일을 사용하기 위해 설정
dot.config();
// bodyparser 필요없이 바로 body객체를 이용할수 있다.
app.use(express.urlencoded({ extended: false }));
//헤더에 쿠키를 추가하기 위해서 사용
app.use(cookie());
//사용자 정보 객체 하나 더미
const user = {
id: "taesk",
password: "123",
};
app.get("/", (req, res) => {
fs.readFile("view/index.html", "utf-8", (err, data) => {
console.log(err);
res.send(data);
});
});
app.post("/login", (req, res) => {
//아이디 비밀번호
const { userId, userPw } = req.body;
//아이디 비밀번호 검증
if (userId === user.id && userPw === user.password) {
// access token 발급
const accessToken = jwt.sign(
{
id: user.id,
},
process.env.ACCESS_TOKEN_KEY,
{
expiresIn: "5m",
}
);
// refresh token 발급
const refreshToken = jwt.sign(
{
id: user.id,
},
process.env.REFRESH_TOKEN_KEY,
{
expiresIn: "1d",
}
);
//쿠키의 이름은 refresh 유효 시간은 하루
res.cookie("refresh", refreshToken, { maxAge: 24 * 60 * 60 * 1000 });
// fs에 readFile함수를 사용해서 join.html을 불러온다. res의 send함수로 응ㄷㅂ
fs.readFile("view/join.html", "utf-8", (err, data) => {
res.send(accessToken, data);
});
return res.send(accessToken);
} else {
return res.send("아이디 비밀번호 오류");
}
});
app.post("/refresh", (req, res) => {
//?. 뒤에 오는 키값이 있으면 먼저 확인하고 값 반환
// 키값이 없어도 크래쉬 방지
if (req.cookies?.refresh) {
const refreshtoken = req.cookies.refresh;
// refresh token이 정상인지 확인
jwt.verify(refreshtoken, process.env.REFRESH_TOKEN_KEY, (err, decode) => {
//에러가 있으면 refresh token이 썩었기 때문에 다시 로그인 시킨다.
if (err) {
res.send("로그인을 다시 하세요");
} else {
//err가 없고 정상적인 토큰이면 다시 access token발급
// jwt에 sign함수로 토큰 다시 생성
const accessToken = jwt.sign(
{
//token의 payload값
id: user.id,
},
//토큰을 암호화시킬 key값
process.env.ACCESS_TOKEN_KEY,
{
expiresIn: "10m",
}
);
res.send(accessToken);
}
});
} else {
res.send("다시 로그인 해주세요");
}
});
app.listen(3000, () => {
console.log("서버열림");
});
'개발 > node.js' 카테고리의 다른 글
[Node.js] crypto, bcrypto (0) | 2022.08.17 |
---|---|
[Node.js] access token, refresh token 을 활용하여 로그인 유지시키기 (0) | 2022.08.16 |
[Node.js] exports router (0) | 2022.08.10 |
[Node.js] 로그인시 jwt과 session (0) | 2022.08.09 |
[Node.js] 로그인시 JWT생성 (0) | 2022.08.09 |