JWT를 사용한 간단한 인증 시스템

지난 포스팅에 이어 멀티플레이 TicTacToe 게임에 JWT(Json Web Token)를 이용하여 인증 시스템을 구현해보도록 하겠습니다.

Live Website
Source Code

JWT란?



JWT는 백엔드에서 생성되어 프런트엔드로 전달된 인증 토큰이며 프런트엔드는 보호된 API 경로에 액세스하기 위한 요청과 함께 이 토큰을 보낼 수 있습니다. 사용자 X의 요청이 실제로 사용자 X 자체에 의해 이루어졌는지 확인하기 위한 것입니다. 일반적으로 JWT 토큰은 만료 시간으로 생성됩니다.

여기에는 JWT 사용에 대한 단점이 있습니다. 생성되었지만 아직 만료되지 않은 모든 토큰은 여전히 ​​보호된 API 경로에 액세스하는 데 사용할 수 있습니다. 일반적으로 원하는 것이 아닙니다.

Little disclaimer here: I think JWT itself is actually very simple, but implementing it the right way is the hard part, so if you know a better way or have a correction, please let me know! thanks.


JWT 취소 방법



따라서 토큰의 액세스를 무효화하고 제한하기 위해 내가 찾은 것은 주로 2가지 방법입니다.
  • 토큰을 블랙리스트/화이트리스트에 추가합니다.
  • 토큰에 대해 사용자별 비밀 키를 사용합니다.

  • 솔직히 아직 장단점은 잘 모르겠지만 두 번째 방법을 사용하겠습니다.

    사용자 개인 키 생성



    note: all of the examples shown are simplified version



    const bcrypt = require('bcrypt');
    
    function generatePersonalKey() {
      return bcrypt.genSaltSync(10);
    }
    


    먼저 개인 키, 무작위 문자열, 숫자 등과 같은 키를 생성하는 함수를 만들어야 합니다. 그러나 여기에서는 bcrypt 패키지를 사용하여 무작위 솔트를 생성하여 generatePersonalKey()를 생성했습니다.

    const mongoose = require('mongoose');
    
    const UserSchema = new mongoose.Schema({
      username: String,
      password: String,
      personalKey: String,
    });
    


    그리고 예를 들어 my UserSchema ( mongoose ) 사용자가 생성될 때 personalKey를 초기화합니다. 그리고 사용자가 로그아웃할 때 우리는 personalKey를 재생성합니다. 이렇게 하면 이전의 토큰은 다른 키를 사용했기 때문에 항상 유효하지 않습니다.

    JWT 생성




    const jwt = require('jsonwebtoken');
    
    const payload = { username: 'khusyasy' };
    const token =
      jwt.sign(payload, user.personalKey, {
        expiresIn: '1h',
      });
    


    토큰 자체를 생성하기 위해 jsonwebtoken 패키지를 사용했습니다. 실제로는 위의 예와 같이 매우 간단합니다. 그런 다음 브라우저에서 javascript를 사용하여 토큰을 설정/가져올 수 없도록 플래그httpOnly로 응답 쿠키를 설정합니다.

    승인 확인 중



    내가 이것에 대해 처음 읽었을 때 나는 매우 혼란스러웠습니다. 토큰을 읽을 수 없다면 어떤 키를 사용해야 하는지 어떻게 알 수 있습니까?
    decode를 사용하여 페이로드를 읽고 사용자 personalKey를 가져온 다음 personalKey를 사용하여 토큰 자체를 확인하면 됩니다. 예를 들어:

    const payload = jwt.decode(token);
    
    const user = await User.findOne({ username: payload.username });
    
    try {
      const verified = jwt.verify(token, user.personalKey);
      // token is verified
    } catch (err) {
      // token is invalid
    }
    


    오늘은 여기까지입니다. 읽어주셔서 감사합니다!

    사용한 패키지:


  • bcrypt
  • jsonwebtoken
  • mongoose
  • 좋은 웹페이지 즐겨찾기