Just Do IT!

Node.js에서 JWT(JSON Web Token) 활용하기 본문

개발 공부/Node.js

Node.js에서 JWT(JSON Web Token) 활용하기

MOON달 2024. 1. 10. 17:00
728x90

JSON Web Token이란?

JSON 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token

토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다. 

주로 회원 인증이나 정보 전달에 사용된다.

 

공식 홈페이지에서 더 많은 정보를 알 수 있다.

https://jwt.io/

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

 

 

 

 

 

 

JWT는 왜 사용할까?

유저가 로그인에 성공한 후에는 access token이라고 하는 암호화된 유저 정보를 첨부해서 request를 보내게 된다. 

그러면 서버에서는 access token을 복호화 해서 해당 유저 정보를 얻게 된다.

이는 매번 반복해서 로그인할 필요 없이 해당 유저의 정보를 저장하는 것이다.


access token 을 생성하는 방법은 여러가지가 있는데, 그 중 가장 널리 사용되는 기술중 하나가 JWT(JSON Web Tokens)이다. JWT는 말 그대로 유저 정보를 담 JSON 데이터를 암호화 해서 클라이언트와 서버간에 주고 받는 것이다.

 

 

 

 

 

 

 

JWT 구조

 

헤더 (header) - 내용(payload) - 서명(signature)

JWT을 복호화하면,

Header에는 알고리즘과 타입, Payload에는 데이터가 있고,

SIGNATURE는 토큰을 인코딩하거나 유효성 검증을 할 때, 사용하는 고유한 코드가 들어있다.

 

Header

typ과 alg 두 가지 정보로 구성된다. 

typ는 토큰 유형을 나타내며, alg는 사용중인 서명 알고리즘을 나타낸다. 

이후 Base64Url로 인코딩되어 JWT의 header 부분을 형성하게 된다.

 

Payload

토큰에서 사용할 정보의 조각들인 클레임(Claim)이 담겨 있다. JSON(key-value) 형태로 다수의 정보를 넣을 수 있다.

 

  • Registerd claims (등록된 클레임)
    • 유용하고 상호 운용 가능한 클레임을 제공하기 위해 필수는 아니지만 권장되는 미리 정의된 클레임 집합이다.
    • 그중 일부는 iss (issuer), exp (expiration), sub (subject), aud (audience) 등이 있다.
  • Public claims (공개 클레임)
    • 공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 한다.
    • 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓는다.
  • Private claims (비공개 클레임)
    • 등록된 클레임도아니고, 공개된 클레임들도 아니다.
    • 클라이언트-서버 협의하에 사용되는 클레임 이름들이다.
    • 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할 때 유의해야 한다.

 

Signature

토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드

서명 부분을 만들기 위해서는 인코딩된 헤더, 인코딩된 페이로드, secret, 헤더에 지정된 알고리즘을 가져와야 한다.

 

(참고: https://velog.io/@hxyxneee/JSON-Web-Token%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90)

 

 

 

 

 

JWT의 단점

  • 사용자 계정을 차단하거나 비활성화해야하는 경우 응용 프로그램은 잠금이 완전히 적용되도록 토큰이 만료 될 때까지 기다려야한다.
  • 토큰이 만료되면 사용자는 다시 인증해야 하는 번거로움이 생길 수 있다.
  • 토큰은 브라우저에서 삭제 되더라도 만료될 때까지 유효하므로 실질적인 로그 아웃이 불가능하다. 따라서 토큰 만료 시간을 꼭 넣어주어야 한다.
  • 토큰의 내용 (Payload)에 3종류의 클레임을 저장하기 때문에, 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.

 

 

 

 

 

 

JWT 실제 적용해보기

설치

npm install jsonwebtoken --save

 

token 생성 (sign 메소드 사용)

토큰을 만들어주어 클라이언트에 발급해주는 메소드이다.

 

  // jsonwebtoken을 이용해서 token 생성
  var token = jwt.sign(user._id.toHexString(), "secretToken");

 

검증하기 (verify 사용)

발급받은 토큰이 제대로 만들어진 토큰인지 확인해주는 메소드이다.

발급받은 토큰으로 api 요청하고 응답받는 api를 만들 때 사용할 수 있다.

 

userSchema.statics.findByToken = function (token, cb) {
  var user = this;

  // 토큰을 decode 한다
  jwt.verify(token, "secretToken", function (err, decoded) {
    // 유저 아이디를 이용해서 유저를 찾은 다음에
    // 클라이언트에서 가져온 token과 db에 보관된 토큰이 일치하는지 확인

    user.findOne({ _id: decoded, token: token }, function (err, user) {
      if (err) return cb(err);
      cb(null, user);
    });
  });
};

 

 

 

로그인 예제

// index.js

...

// login
app.post("/api/login", (req, res) => {
  // 요청된 이메일을 데이터베이스에서 있는지 찾는다
  User.findOne({ email: req.body.email }, (err, userInfo) => {
    if (!userInfo) {
      return res.json({
        loginSuccess: false,
        message: "제공된 이메일에 해당하는 유저가 없습니다.",
      });
    }

    // 있다면 비밀번호가 같은지 확인
    user.comparePassword(req.body.password, (err, isMatch) => {
      if (!isMatch)
        return res.json({
          loginSuccess: false,
          message: "비밀번호가 틀렸습니다",
        });

      // 비밀번호까지 같다면 Token을 생성
      user.generateToken((err, user) => {
        if (err) return res.status(400).send(err);

        // token을 저장한다 (쿠키, 로컬스트리지에 저장 가능) => 여기서는 쿠키에 저장
        res
          .cookie("x_auth", user.toekn)
          .status(200)
          .json({ loginSuccess: true, userId: user._id });
      });
    });
  });
});

...

 

'개발 공부 > Node.js' 카테고리의 다른 글

Bcrypt를 통해 비밀번호 암호화하기  (1) 2024.01.10
mongoose 사용하기  (1) 2024.01.05
NodeJS와 express 알아보기  (1) 2024.01.02