본문 바로가기

Node.js/서버

JWT토큰

1. 종류

  • Access Token: 실제로 API 접근 권한을 부여하는 토큰. 리소스에 접근할 때 사용
  • Refresh Token: Access Token이 만료됐을 때 새로운 Access Token을 발급받기 위한 토큰 유효기간

2. 유효기간

  • Access Token: 짧게 설정 (보통 15분~2시간)
  • Refresh Token: 길게 설정 (보통 7일~30일)

3. 저장 위치

  • Access Token: 클라이언트만 저장 (localStorage나 메모리)
  • Refresh Token: 클라이언트와 서버 DB 둘 다 저장

 

 

굳이 토큰을 두개로 나누는 이유.

  1. 보안 강화: Access Token이 탈취되어도 짧은 유효기간 때문에 피해 최소화
  2. 사용자 경험: Refresh Token으로 자동 재발급하여 잦은 로그인 방지
  3. 토큰 관리: Refresh Token만 DB에 저장하여 서버 부하 감소

------------------------코드-------------------------------

 

엑세스토큰 생성

    static createAccessToken(user) {
        return jwt.sign(
            { user_id: user.user_id },
            process.env.ACCESS_SECRET,
            { expiresIn: '15m' } // 만료시간 15분
        );
    }

 

리프레시토큰 생성 + DB 저장

static async createRefreshToken(user) {
        // 리프레시토큰을 만들기 전에 기존의 리프레시토큰 삭제
        await db.query(
            `DELETE FROM refresh_tokens WHERE user_id = ?`,
            [user.user_id]
        );
        const refreshToken = jwt.sign(
            { user_id: user.user_id },
            process.env.REFRESH_SECRET,
            { expiresIn: '30d' }, // 만료시간 30일
        );

        // 만료시간 계산
        const expires_at = new Date();
        expires_at.setDate(expires_at.getDate() + 30);
        // db에 저장
        await this.saveToken(user.user_id, refreshToken, expires_at);
        return refreshToken;
    }
    static async saveToken(user_id, token, expires_at) {
        const [result] = await db.query(
            `INSERT INTO refresh_tokens(user_id, token, expires_at)
                VALUES (?, ?, ?)`,
            [user_id, token, expires_at]
        );
        return result.insertId;
    }

 

토큰 재발급

    static async refreshAccessToken(refreshToken) {
        const newToken = await this.verifyRefreshToken(refreshToken);
        if (!newToken) {
            throw new Error('토큰 발급 실패');
        }
        return this.createAccessToken({ user_id: newToken.user_id })
    }

 

 

리프레시토큰 검증 + DB에서 만료되지 않은 토큰 찾기

    static async verifyRefreshToken(token) {
        const isToken = await this.findToken(token);
        if (!isToken) {
            throw new Error('유효하지 않은 토큰');
        }
        return jwt.verify(token, process.env.REFRESH_SECRET);
    }
    static async findToken(token) {
        const [result] = await db.query(
            `SELECT * FROM refresh_tokens WHERE token = ? AND expires_at > NOW()`,
            [token]
        );
        return result[0];
    }

'Node.js > 서버' 카테고리의 다른 글

morgan, cookie-parser, express-session  (0) 2024.09.21
미들웨어  (0) 2024.08.11
쿠키와 세션  (0) 2024.08.11
express 사용하기  (0) 2024.08.03
npm 시작하기  (0) 2024.07.30