Node.js - JWT 기본 사용 개념(with passport)

ryan·2022년 5월 20일
0

JWT (JSON Web Token)

  • 인증을 위한 정보를 특별한 저장소를 이용하지 않고, 전자 서명을 이용하여 확인하는 방법

JWT의 구성

  • header : 토큰의 타입(jwt), 데이터 서명 방식
  • payload : 전달되는 데이터
  • signature : 헤더와 페이로드의 전자서명
  • WEB Token, 데이터를 웹에서 사용하기 위한 스펙이므로 웹에서 문제없이 사용할 수 있는 문자열로만 구성된 base64 인코딩을 사용
  • jwt 홈페이지에서 JWT Encode/Decode를 실행해 볼 수 있음.

JWT와 보안

  • JWT의 payload는 단순히 정보를 base64 encode하며, decode 시 정보가 노출됨.
  • 민감한 정보는 제외하고 토큰을 생성해야 함.
  • 서버는 JWT를 생성할 때, 비공개키를 이용하여 서명을 한다. payload를 조작할 경우 서명이 일치하지 않기 때문에 인증 실패.

JWT 작동 방식

  • 사용자 로그인
  • 서버는 로그인 유저 정보를 JWT로 생성해서 클라이언트 저장
  • 클라이언트는 전달받은 JWT를 이용하여 인증이 필요한 요청에 사용

JWT 사용 이유

  • session은 기본적으로 웹 브라우저의 통신 스펙
  • 모바일 앱 등, 웹 브라우저가 아닌 어플리케이션의 경우 이를 활용하기 부적합함
  • jwt를 사용하면 어느 클라이언트에서나 동일한 방식의 사용자 인증을 구현 가능
  • 웹 서비스에서 사용하는 정보를 클라이언트에 저장하고, HTTP 요청 시 이를 함께 전송하여, 클라이언트 정보를 서버에 전달하는 기술
  • session : 클라이언트 정보를 서버 측 저장소에 저장하고 사용
  • cookie : 클라이언트 정보를 클라이언트(브라우저)에 저장하고 사용
  • session을 사용한 유저 로그인의 경우 cookie에 session id 저장 . session store에서 유저 정보 가져오기
  • jwt를 쿠키에 저장하는 경우, jwt로 요청 > 서명 확인 후 유저 정보 사용
  • 데이터베이스 접근이 줄어서 효율적인 인증 구현 가능

JWT 로그인 구현

  • 기존 세션으로 구현된 로그인을 비활성화
  • 로그인 로직에서 JWT 생성 후 쿠키로 전달
  • passport-jwt 패키지로 jwt 로그인 미들웨어 작성 및 사용

EX. passport-jwt 패키지 사용

// 로그인 로직에 jwt 토큰 생성 및 쿠키 전달
const passport = require('passport');

// res.cookie 함수 사용하여 token을 클라이언트에 쿠키로 전달
setUserToken = (res, use) => {
  const token = jwt.sign(user, secret); // jwt 토큰 생성
  res.cookie('token', token); // 'token'이라는 이름의 쿠키를 생성한 토큰을 넣어서 응답
};

router.post('/', passport.authenticate('local'), (req, res, next) => {
  setUserToken(res, req.user); 
  //req.user 정보를 바탕으로 서명된 jwt가 cookie에 저장되어 res에 넣어짐
  res.redirect('/');
});

// passport-jwt 패키지를 이용해, 요청된 jwt 토큰의 서명을 확인하고 인증하는 기능을 구현
const JwtStrategy = require('passport-jwt').Strategy;
const cookieExtractor = (req) => {
  const {token} = req.cookies; // req.cookies에서 token을 추출하고 token을 반환
  return token;
};
const opts = {
  secretOrKey: secret, // jwt 토큰을 생성할 때 만들었던 secret 변수
  jwtFromRequest: cookieExtractor, //
};
module.exports = new JwtStrategy(opts, (user, done) => {
  done(null, user);
});

passport.use(jwt);

EX. JWT Middleware

  • JWT 미들웨어 추가
  • JWT 토큰은 기본적으로 모든 요청에 포함
  • 요청에 토큰이 있는 경우 로그인된 상태로 처리하기 위해, 모든 요청에 공통적으로 적용할 수 있는 미들웨어로 JWT 로그인을 추가
const passport = require('passport');
app.use((req, res, next) => {
  if ((!req.cookies, token)) {
    next(); // req에 쿠키가 없다면 로그인 안된 상태로 넘어가기
    return;
  }
  return passport.authenticate('jwt')(req, res, next); 
  // jwt Strategy를 사용하여 인증을 하고 req에 저장
});


jwt logout 구현
// 클라이언트 쿠키를 삭제하여 처리 가능
res.cookie('token', null, {
  // 쿠키에 null 값을 전달해주고 쿠키의 만료 시간을 0으로 설정하여 
  // 클라이언트가 쿠키를 바로 만료시키도록 전달
  maxAge: 0,
});
profile
프론트엔드 개발자

0개의 댓글