[Node.js & express] JWT로 로그인 구현하기

Hyein Kim·2021년 5월 24일
1

💚 Node.js

목록 보기
2/3
post-thumbnail

passport.js란?

사용자를 인증하기 위해 사용하는 Node.js용 미들웨어

JWT란?

JWT(JSON Web Token)은 클라이언트와 서버 혹은 서비스 간의 통신시 정보를 JSON 객체를 통해 안전하게 전송하고 권한(Authorization)을 위해 사용하는 토큰이다.

필요한 모듈 설치

  • passport
  • passport-local
  • passport-jwt
  • jsonwebtoken
npm install passport passport-local passport-jwt jsonwebtoken --save

app.js

// app.js
...

const passport = require('passport');
const passportConfig = require('./passport');

...

app.use(passport.initialize());
passportConfig();

config/passport.js

// config/passport.js
var db = require('./db');
var conn = db.init();
const bcrypt = require('bcrypt');
const passport = require('passport');
const passportJWT = require('passport-jwt');
const JWTStrategy = passportJWT.Strategy;
const { ExtractJwt } = passportJWT;
const LocalStrategy = require('passport-local').Strategy;

db.connect(conn);

const LocalStrategyOption = {
  usernameField: "user_id",
  passwordField: "password"
};
async function localVerify(user_id, password, done) {
  var user;
  try {
    var sql = 'select * from user where user_id = ?';
    var params = [user_id];
    await conn.query(sql, params, async function (err, rows, fields) {
      if(err) {
        console.log(err);
        return done(null, false);
      }
      if(!rows[0]) return done(null, false);
      user = rows[0];

      console.log(password, user.password);
      const checkPassword = await bcrypt.compare(password, user.password);
      console.log(checkPassword);
      if(!checkPassword) return done(null, false);

      console.log(user);
      return done(null, user);
    }) 
  } catch (e) {
    return done(e);
  }
}

const jwtStrategyOption = {
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: 'jwt-secret-key',
};
async function jwtVerift(payload, done) {
  var user;
  try {
    var sql = 'select * from user where user_id = ?';
    var params = [payload.user_id];
    await conn.query(sql, params, function (err, rows, fields) {
      if(!rows[0]) return done(null, false);
      user = rows[0];

      console.log(user);
      return done(null, user);
    });
  } catch (e) {
    return done(e);
  }
}

module.exports = () => {
  passport.use(new LocalStrategy(LocalStrategyOption, localVerify));
  passport.use(new JWTStrategy(jwtStrategyOption, jwtVerift));

controllers/authController.js

// controllers/authControllers.js
var express = require('express');
var db = require('../db');
var conn = db.init();
const passport = require('passport');
const jwt = require('jsonwebtoken');

db.connect(conn);

const login =  async (req, res, next) => {
  try {
    passport.authenticate('local', { session: false }, (err, user) => {
      if (err || !user) {
        console.log(err);
        return res.status(400).json({success : false, message : "로그인 실패"});
      }
      req.login(user, { session: false }, (err) => {
        if (err) {
          console.log(err);
          return res.send(err);
        }
        const token = jwt.sign(
          { user_id : user.user_id },
          'jwt-secret-key',
          {expiresIn: "7d"}
        );
        return res.json({ success : true, message : "로그인 성공", token });
      });
    })(req, res);
  } catch (e) {
    console.error(e);
    return next(e);
  }
};

const check =  (req, res) => {
  res.json(req.decoded);
};

module.exports = {
  login,
  check
}

middleware/auth.js

// middleware/auth.js
const jwt = require('jsonwebtoken');

exports.verifyToken = (req, res, next) => {
  try {
    const token = req.headers.authorization.split('Bearer ')[1];
    let jwt_secret = 'jwt-secret-key';

    req.decoded = jwt.verify(token, jwt_secret);
    return next();
  } catch (err) {
    if (err.name == 'TokenExpiredError') {
      return res.status(419).json({success: false, message : "token 만료"});
    }
    return res.status(401).json({success: false, message : "token이 유효하지 않습니다."});
  }
}

routes/authRouter.js

// routes/authRouter.js
const express = require('express');
const router = express.Router();
const { authController } = require('../controllers');
const { verifyToken } = require('../middleware/auth');

router.post('/login', authController.login);
router.get('/check', verifyToken ,authController.check);

module.exports = router;

테스트

  • POST /auth/login
    아이디, 비밀번호를 json request로 전송하면 token이 발급된다.
  • GET /auth/check
    토큰 값을 헤더에 넣어 전송하면 토큰이 유효한지 검사한 후 user 정보를 보내준다.

profile
I'm free

0개의 댓글