서버/Express

ExpressJS JWT

realtrynna 2022. 3. 26. 10:25

Nodejs Express JWT

JSON 형식 데이터를 저장하는 토큰 3가지 형식으로 구성된다.

1. 헤더(HEADER)

토큰의 종류와 해시 알고리즘 정보 저장된다.

 

2. 페이로드(PAYLOAD)

데이터가 인코딩되어 저장된다.

 

3. 시그니처(SIGNATURE)

일련의 문자열 시그니처를 통해 토큰이 변/위조되었는지 파악 확인한다.

시그니처는 JWT 비밀키로 만들어진다.

비밀키가 노출되지 않는 이상 변조/위조 불가능하다.

 

jwt.io

 

 

WHY TO USE IT

- 토큰에 내용물이 들어있어 데이터베이스에서 조회를 하지 않아도 된다.

- 토큰의 시그니처에 비밀키가 노출되지 않는 이상 해킹 불가능하다.

- 비밀키만 잘 관리하면 데이터(PAYLOAD)를 믿고 사용할 수 있다.

- 이름 / 권한 등 민감하지 않은 정보만 넣어야 한다.

- 토큰의 용량도 크고 네트워크 요청 시 토큰이 오고 가서 데이터 트래픽 증가한다.

- 장단점을 비교하여 사용한다.

- 클라이언트 토큰이 만료가 되면 사라지는 게 아니라 만료 토큰으로 남아있다.

 

설치

- JWT 모듈과 비밀키 관리를 위해 dotenv 모듈 설치

 

 

.env 설정

process.env.JWT_SECRET

 

 

토큰 검사를 위한 JWT 미들웨어

- jwt.verify 메서드로 검사한다.

- 토큰은 req.headers.authorization에 들어 있다.

- 토큰 만료(419) 유효하지 않은 토큰(401)

- 토큰의 비밀키와 토큰의 유효 기간이 지나면 catch 문으로 이동한다.

- 토큰 인증 성공 시 req.decoded에 저장된다.

- req.decoded를 통해 다음 미들웨어에서 토큰의 페이로드 확인 가능하다.

 

routes ㅡ> middlewares.js
const jwt = require("jsonwebtoken");

exports.verifyToken = (req, res, next) => {
  try {
    req.decoded = jwt.verify(req.headers.authorization, process.env.JWT_SECRET);
    return next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(419).json({
        code: 419,
        message: "토큰 만료",
      });
    }
    return res.status(401).json({
      code: 401,
      message: "유효하지 않은 토큰",
    });
  }
};

 

 

토큰 발급 라우터

- 기존 서비스 도메인 등록 여부 확인한다.

- jwt.sing 메서드로 토큰 발급한다.

 

const express = require("express");
const jwt = require("jsonwebtoken");

const { verifyToken } = require("./middlewares");
const { User, Domain, Post, Hashtag } = require("../models");

const router = express.Router();

router.post("/token", async (req, res, next) => {
  const { clientSecret  } = req.body;
  try {
    const domain = await Domain.findOne({ // 도메인 등록 여부 검사
      where: { clientSecret },
      include: {
        model: User,
        attributes: [ "id", "name" ],
      }
    });
    if (!domain) { // 도메인 없을 시 에러 처리
      return res.status(401).json({
        code: 401,
        message: "도메인 먼저 등록하세요.",
      });
    }
    const token = jwt.sign({
      id: domain.User.id,
      name: domain.User.name,
    }, process.env.JWT_SECRET, {
      expiresIn: "2m",
      issuer: "axisotherwise",
    });
    return res.json({
      code: 200,
      message: "token success",
      token,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({
      code: 500,
      message: "server error",
    });
  }
});

module.exports = router;

'서버 > Express' 카테고리의 다른 글

ExpressJS MySQL CRUD  (0) 2022.05.14
ExpressJS CORS(Cross-Origin-Resource-Sharing)  (0) 2022.03.28
ExpressJS method-override  (0) 2022.03.22
ExpressJS middleware  (0) 2022.01.22
ExpressJS nunjucks  (0) 2022.01.20