일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 백준 32028번
- router
- ucpc 2023 예선 i번
- insomnia
- localstorage
- JavaScript
- Prisma
- 백준 28303번
- ucpc 2023 예선 d번
- Next
- html5
- 자바스크립트
- ERD
- Express.js
- MongoDB
- MySQL
- 백준 32029번
- HTTP
- 게임 서버 아키텍처
- ccw 알고리즘
- Github
- ucpc 2024 예선 e번
- 그리디
- 지금 자면 꿈을 꾸지만
- string
- map
- 더 흔한 색칠 타일 문제
- branch
- PROJECT
- pm2
Archives
- Today
- Total
dh_0e
[Node.js] 강의 내용 개념 정리(6) (Access Token, Refresh Token) 본문
Access Token
- 사용자의 인증이 완료된 후 해당 사용자를 인증하는 용도로 발급하는 토큰(쿠키에 jwt를 설정하고 만료 시간이 지나면 인증이 만료되는 구조 또한 Access Token)
- 토큰을 생성할 때 사용한 비밀키로 인증을 처리
- Stateless(무상태) 즉, Node.js 서버가 재시작되더라도 동일하게 작동함
- 이는 jwt를 이용해 사용자의 인증 여부는 확인할 수 있지만, 처음 토큰을 발급한 사용자인지 확인할 수는 없음
- 그 자체로 사용자 인증에 필요한 모든 정보를 가지고 있음
- 토큰을 가지고 있는 시간이 늘어날 수록, 탈취되었을 때 피해 규모가 더욱 커짐
Refresh Token
- 사용자의 모든 인증 정보를 담고있는 Access Token과 달리 특정 사용자가 Access Token을 발급받기 위한 목적으로만 사용됨
- 디코딩하여 사용자의 정보를 확인하며 필요한 경우 서버에서 강제로 토큰을 만료시킬 수 있어 사용자의 인증 상태를 언제든지 서버에서 제어할 수 있다는 장점을 가지고 있음
- OTP처럼 사용자의 인증 정보는 짧은 시간동안만 사용되도록 제한하여 피해를 최소화함
ex)
// app.js
import express from "express";
import jwt from "jsonwebtoken";
import cookieParser from "cookie-parser";
const app = express();
const PORT = 3019;
// AccessToken을 발급하는 함수
function createAccessToken(id) {
const accessToken = jwt.sign({ id }, ACCESS_TOKEN_SECRET_KEY, {
expiresIn: "10s",
});
return accessToken;
}
const ACCESS_TOKEN_SECRET_KEY = `Secret Key for Access Token`; // Access Token의 비밀 키를 정의합니다.
const REFRESH_TOKEN_SECRET_KEY = `Secret Key for Refresh Token`; // Refresh Token의 비밀 키를 정의합니다.
app.use(express.json());
app.use(cookieParser());
app.get("/", (req, res) => {
return res.status(200).send("Hello Token!");
});
const tokenStorages = {}; // 리프레시 토큰을 관리할 객체
/* 엑세스, 리프레시, 토큰 발급 API */
app.post("/tokens", async (req, res) => {
const { id } = req.body;
//엑세스 토큰과 리프레시 토큰을 발급
const accessToken = createAccessToken(id);
const refreshToken = jwt.sign({ id }, REFRESH_TOKEN_SECRET_KEY, {
expiresIn: "7d",
});
tokenStorages[refreshToken] = {
id,
ip: req.ip,
userAgent: req.headers["user-agent"], // 특정 클라이언트가 어떤 방식으로 서버에 요청을 했는지
};
// 클라이언트에게 쿠키(토큰)을 할당
res.cookie("accessToken", accessToken);
res.cookie("refreshToken", refreshToken);
return res.status(200).json({ message: "토큰이 정상적으로 발급됨" });
});
/* Access Token 검증 API */
app.get("/tokens/validate", async (req, res) => {
const { accessToken } = req.cookies;
//Access Token이 존재하는지 확인
if (!accessToken) {
return res
.status(401)
.json({ errorMessage: "Access Token이 존재하지 않음" });
}
const payload = validateToken(accessToken, ACCESS_TOKEN_SECRET_KEY);
if (!payload) {
return res
.status(401)
.json({ errorMessage: "Access Token이 정상적이지 않음" });
}
const { id } = payload;
return res.status(200).json({
message: `${id}의 Payload를 가진 Token이 정상적으로 인증 되었습니다.`,
});
});
// 토큰을 검증하고, Payload를 조회하기 위한 함수
function validateToken(token, secretKey) {
try {
return jwt.verify(token, secretKey);
} catch {
return null;
}
}
/* Refresh Token을 이용해서 Access Token을 재발급 받는 API */
app.post("/tokens/refresh", async (req, res) => {
const { refreshToken } = req.cookies;
if (!refreshToken) {
return res
.status(400)
.json({ errorMessage: "Refresh Token이 존재하지 않습니다." });
}
const payload = validateToken(refreshToken, REFRESH_TOKEN_SECRET_KEY);
if (!payload) {
return res
.status(401)
.json({ errorMessage: "Refresh Token이 정상적이지 않습니다." });
}
const userInfo = tokenStorages[refreshToken];
if (!userInfo) {
return res
.status(419)
.json({ errorMessage: "Refresh Token이 서버에 존재하지 않습니다." });
}
const { id } = payload;
const accessToken = createAccessToken(id);
res.cookie("accessToken", accessToken);
return res.status(200).json({ message: "Access Token 재발급 완료" });
});
app.listen(PORT, () => {
console.log(PORT, "포트로 서버가 열렸어요!");
});
- tokenStorage 객체처럼 리프레시 토큰을 저장할 객체는 로컬이 아닌 아래와 같이 db에 테이블을 따로 만들어 저장하는 것이 좋다.
user-agent: 요청한 클라이언트 정보를 알 수 있음
req.headers["user-agent"]
'내일배움캠프 > Node.js[숙련]' 카테고리의 다른 글
[Node.js] 강의 내용 개념 정리(8) (Prisma Transaction, express-session) (0) | 2024.05.28 |
---|---|
[Node.js] 강의 내용 개념 정리(7) (로그 미들웨어, Transaction) (0) | 2024.05.28 |
[Node.js] 강의 내용 개념 정리(5) (인증, 인가, 사용자 인증 미들웨어) (0) | 2024.05.27 |
[Node.js] 강의 내용 개념 정리(4) (JWT) (0) | 2024.05.24 |
[Node.js] 강의 내용 개념 정리(3) (Cookie, Session) (0) | 2024.05.24 |