토큰을 발행해준 후, verify 과정에서 Invalid, expired를 처리해줘야 할까 고민이 들었습니다. 그래서 상황에 맞는 시나리오를 그리고 어떻게 해결해 나갈 것인지 코드를 작성하였습니다.

시나리오

1. 로그인을 하면 AccessToken과 RefreshToken을 발행합니다.
 - AccessToken은 Bearer, RefreshToken은 Redis에 저장을 해줍니다.

2. 사용자가 인증일 필요한 API에 접근하고자 할 때, 검증 미들웨어(authMiddleware)를 통해 검사함.
 

  • Case 1 : AccessToken 만료, RefreshToken 만료  : Error
  • Case 2 : AccessToken 만료, RefreshToken 유효 : AccessToken 재발급
  • Case 3 : AccessToken 유효, RefreshToken 만료 : 로그인 재요청
  • Case 4 : AccessToken 유효, RefreshToken 유효 : next

3. 로그아웃

  • AccessToken, RefreshToken 삭제시키기.

🛠Advanced Feacture🛠

const authMiddleware = {

    checkToken: async (req, res, next) => {

        try {
            // accessToken이 만료된 경우에는 새로 발급 받은 accessToken을 받아옵니다. 그 외에는 null로 넘겨줬습니다.
            const { accessToken, result } = await authService.verifyToken(req);
			
            //result를 통해서 ( "(AccessToken||RefreshToken)_(INVALID||EXPIRED)" 를 받아옵니다.
            
            //AccessToken이 변조된 경우
            if (result === ACCESSTOKEN_INVALID) {
                return res.status(403).send({ err: "accessToken is invalid", statusCode: 403, msg: 'Forbidden' });
            }
            //RefreshToken이 변조된 경우
            else if (result === REFRESHTOKEN_INVALID) {
                return res.status(401).send({ err: "refreshToken is invalid", statusCode: 401, msg: '재로그인 해주세요' });
            }
            //AccessToken이 만료된 경우            
            else if (result === ACCESSTOKEN_EXPIRED) {
            	//새로 받아온 accessToken을 Bearer + 새로 발급받은 accessToekn을 넣어줍니다.
                res.header('AccessToken', "Bearer " + accessToken);
                return next();
            }
            //RefreshToken이 만료된 경우
            else if (result === REFRESHTOKEN_EXPIRED) {
                return res.status(401).send({ statusCode: 401, msg: '재로그인 해주세요' });
            }
            //둘다 유효한 경우에는 기존의 accessToken을 넘겨줍니다.
            res.header('AccessToken', "Bearer " + accessToken);

            return next();
        } catch (error) {
        	//둘다 만료인 경우에는 에러
            error.status = 500;
            error.msg = 'token is not found';
            next(error);
        }
    }
}

 

 

 

플로우

코드를 작성해 나가면서 위의 플로우처럼 모든 시나리오를 수행하는 방법도 있을 수 있지만, 다른 방법이 있지 않을까라는 생각이 들었습니다.  

예를 들어, 토큰이 만료되었다고 클라이언트 측에서 재발급 요청을 한다거나 하는 그런 플로우도 가능하지 않을까 생각을 했습니다.
하지만, 그렇게되면 불필요한 요청이 많아지는 것을 확인할 수 있었습니다.

+ Recent posts