Refresh Token 구현하기

Seungeun·2024년 6월 19일

로그인&회원가입

목록 보기
3/3
post-thumbnail

로그인 마지막 시리즈이다

0. 개요

  1. 회원가입과 암호화방식 알아보기
  2. JWT와 로그인
    3. Refresh Token을 이용한 로그인, Authorization

왜 Refresh Token?

Access Token으로만 인증을 하다보면 보안이 취약하기 때문에 Refresh Token도 같이 발행해준다는 이야기를 지난 2편에서 했다. 이번에는 어떤 방식으로 흘러가는지 정리하고 코드로 구현해보려한다.

Access Token & Refresh Token 작동방식

코드 구현

Access Token만 발행할 때와 달라지는 수정사항

users/userService.js

  1. login 모듈에서 refresh Token도 함께 발행해주어야한다.
  2. Refresh Token 발행 후 redis 모듈을 이용해 서버에 저장한다.
if(user && currentPwd == user.password) { 
        
        const token = sign(user);
        const refreshToken = refresh();

        const redisClient = redis.createClient(process.env.REDIS_PORT);
        await redisClient.connect();
        redisClient.set(toString(user.id), refreshToken);

        res.cookie('token', {token: token, refreshToken: refreshToken}, {httpOnly : true})
        res.status(StatusCodes.OK).json(result)
    }      
  1. refresh.js 파일 생성 후 access 재발급 요청에 대한 모듈 작성추가
const { StatusCodes } = require('http-status-codes');
const {sign, verify, refreshVerify} = require('./jwt-utils');
const jwt = require('jsonwebtoken');

const excRefresh = async (req,res) => {
    const accessToken = req.headers.authorization;
    const refreshToken = req.headers.refresh;

    if(accessToken && refreshToken){
        
        accessResult = verify(accessToken);
        const user = accessResult
        refreshResult = await refreshVerify(refreshToken, user.id);

        //access 만료시
        if(!accessResult.ok) {
            if(!refreshResult.ok){ // refresh 만료시
                res.status(StatusCodes.UNAUTHORIZED).json({
                    message : "로그인 다시"
                })
            } else { // refresh 유효
                //access token 새로 발급
                const newToken = sign(user);
                res.cookie('token', {token: newToken, refreshToken: refreshToken}, {httpOnly : true});
                res.status(StatusCodes.OK).json({message : "새로운 토큰 발급 완료"});
            }
        } else {
            //access not expired
            res.status(StatusCodes.BAD_REQUEST).json({message : "access Token이 만료되지 않았습니다."})
        }
    } else {
        res.status(StatusCodes.BAD_REQUEST).json({
            message : "No Access Token and Refresh Token"
        })
    }
}

module.exports = excRefresh;

코드의 흐름

  1. Refresh Token && Access Token이 모두 헤더에 있으면
    1. access token 만료시
      1. refresh token 유효시 : 토큰 재발급
      2. refresh token 만료시 : 로그인 요청
    2. access token 유효시 : “잘못된 요청 - 만료되지 않았습니다”
  2. 토큰이 존재하지 않습니다.

수정해야할 사항

  1. access token이 만료 시 위에 login.js, refresh.js를 구현하고
    user.js 라우터 파일 안에 밑에 처럼
app.get('/refresh', refresh);

새로운 요청하는 방식으로 작성하고 postman에서 요청해 잘 작동하는지 확인했는데 실제로는 어떻게 작동되는지 알아보아야 한다.


  1. 두개의 token을 Cookie로 보냈는데 set-cookie에 분리되어있지 않아 확인하기가 어려웠다. cookie-parser을 이용해보려 했는데 아직 에러가 나서 재시도 해보아야겠다.

참조 : https://velog.io/@kshired/Express에서-JWT로-인증시스템-구현하기-Access-Token과-Refresh-Token

profile
Wonderland

0개의 댓글