티스토리 뷰

do/nodejs

express login

dooo.park 2019. 4. 9. 14:48

express login/logout 

세션 저장

세션 설정 코드 작성

app.use(express.cookieParser()); 
app.use(express.session({ 
  key: ‘sid’, // 세션키 
  secret: ‘secret’, // 비밀키 
  cookie: { 
    maxAge: 1000 * 60 * 60 // 쿠키 유효기간 1시간 
  } 
})); 

위와 같이 설정하고 나면 Request 객체에서 session 프로퍼티를 가지고 세션을 핸들링할 수 있게 된다.

function (req, res) { 
  req.session.user_id = 1234, // 아이디 
  req.session.name = ‘chris’ // 이름 
} 

 

세션 삭제

로그인 시에 세션을 저장을 했다면, 로그 아웃 시에는 세션 삭제가 이루어져야 한다. 

세션 정보를 완전히 삭제하려면 세션과 쿠키를 함께 삭제해야 하는데, 

쿠키를 삭제하지 않을 경우 쿠키에 저장된 세션 정보로 인해 맞지 않은 세션정보가 호출되는 문제가 발생하기 때문이다.

 

세션을 삭제하기 위해서는 세션 객체에서 제공하는 destory() 메소드로 세션을 삭제하며, 

쿠키는 Response 개체의 clearCookie() 메소드에 세션 생성 시 사용한 키값을 파라 매터로 전달하여 삭제할 수 있다.

exports.logout = function (req, res) { 
  req.session.destory();  // 세션 삭제 
  res.clearCookie(‘sid’); // 세션 쿠키 삭제 
}; 

 

passport 사용하여 구현하기

http://www.passportjs.org/

express로 API서버의 인증 부분을 구축할 때는 패스포트(passport) 모듈을 많이 사용한다. 

인증을 하기위해 클라이언트에서 이메일, 비밀번호를 request body에 담아 서버로 인증 요청을 하면,

서버는 이를 확인해 인증된 클라이언트 정보를 세션에 저장을 하게 되는데 패스포트가 그 역할을 하게 된다.

 

서버에서는 이전에 인증한 클라이언트로 보고 API 응답을 보내 주는 구조였지만, 이번에는 패스포트를 사용하여 OAuth 2.0 방식으로 구현해보자.

 

OAuth 2.0은 인증정보를 담은 Access Token을 사용하므로 세션에 인증정보를 저장할 필요가 없다. 

서버에서는 Access Token을 디코딩하여 확인할 수 있다. 

개발 중 서버가 재 구동되면 그때마다 다시 로그인 프로토콜을 호출해야 하는 번거로움이 있었지만, 

OAuth 2.0을 사용하면 인증 후 획득한 Access Token을 헤더에 넣어서 호출하면 되기 때문에 편리하다. 

passport.js는 패스포트 설정을 위한 코드이다. 

email과 password를 받아 인증을 처리하고 그 결과로 인증한 사용자의 아이디를 넘겨주는 역할을 한다. 

passport.js

'use strict'; 

var passport = require('passport'); 
var LocalStrategy = require('passport-local').Strategy; 

exports.setup = function () { 
  passport.use(new LocalStrategy({ 
        usernameField: 'email', 
        passwordField: 'password' 
      }, 
      function(email, password, done) { 
      // 인증 정보 체크 로직 
        if (email === 'test@test.com' && password === 'test') { 
        // 로그인 성공시 유저 아이디를 넘겨준다. 
          var user = {id: 'user_1'}; 
          return done(null, user); 
        } else { 
          return done(null, false, { message: 'Fail to login.' }); 
        } 
      } 
  )); 
}; 

로그인은 POST /login 라우팅에서 수행한다. 

패스포트 세팅 작업 선행 후, 라우팅 로직을 구현한다.

user.js

'use strict'; 

var express = require('express'); 
var passport = require('passport'); 
var auth = require('./auth'); 

// 패스포트 세팅 
require('./passport').setup(); 

var router = express.Router(); 

// 로그인 라우팅 POST /login 
router.post('/', function(req, res, next) { 

  //  패스포트 모듈로 인증 시도 
  passport.authenticate('local', function (err, user, info) { 
    var error = err || info; 
    if (error) return res.json(401, error); 
    if (!user) return res.json(404, {message: 'Something went wrong, please try again.'}); 

    // 인증된 유저 정보로 응답 
    res.json(req.user); 
  })(req, res, next); 
}); 

module.exports = router; 


JWT

JWT(Json Web Token)는 인증정보를 암호화하여 url 형식으로 전달해 주는 토큰이다. 

OAuth 2.0에서는 JWT Bearer Token Flow를 사용할 수 있기 때문에 JWT를 이용해 토큰을 관리할 것이다.

 

JWT의 설치는 다음과 같다.

npm install jsonwebtoken --save 

 

그 다음 JWT 모듈을 추가하고 auth.js 파일을 만들어 Oauth 2.0 인증에 관한 로직을 작성한다. 

auth.js

'use strict'; 

var jwt = require('jsonwebtoken'); 
var compose = require('composable-middleware'); 
var SECRET = 'token_secret'; 
var EXPIRES = 60; // 1 hour 

// JWT 토큰 생성 함수 
function signToken(id) { 
  return jwt.sign({id: id}, SECRET, { expiresInMinutes: EXPIRES }); 
} 

// 토큰을 해석하여 유저 정보를 얻는 함수 
function isAuthenticated() { 
  return compose() 
      // Validate jwt 
      .use(function(req, res, next) { 
        var decoded = jwt.verify(req.headers.authorization, SECRET); 
        console.log(decoded) // '{id: 'user_id'}' 
        req.user = decode; 
      }) 
      // Attach user to request 
      .use(function(req, res, next) { 
        req.user = { 
          id: req.user.id, 
          name: 'name of ' + req.user.id 
        }; 
        next(); 
      }); 
} 


exports.signToken = signToken; 
exports.isAuthenticated = isAuthenticated; 

 

로그인 로직에서는 auth.js 모듈 중 토큰을 생성하는 signToken() 함수를 사용한다.


login.js

router.post('/', function(req, res, next) { 
  passport.authenticate('local', function (err, user, info) { 
    var error = err || info; 
    if (error) return res.json(401, error); 
    if (!user) return res.json(404, {message: 'Something went wrong, please try again.'}); 

    // access token 생성 
    var token = auth.signToken(user.id); 
    res.json({access_token: token}); 
  })(req, res, next); 
}); 

인증을 필요로 하는 프로토콜 인 GET /users는 auth모듈의 isAuthenicated() 함수로 인증된 클라이언트임을 보장한다.

user.js

/* GET users listing. */ 
router.get('/', auth.isAuthenticated(), function(req, res) { 
  res.send(req.user); 
}); 

node.js 모듈인 express-jwt는 두 가지 역할을 수행한다. 

① 인증된 클라이언트의 액세스 토큰을 디코딩하고

② 인증된 유저정보를 req.user에 저장한다.

 

내부적으로는 jsonwebtoken 모듈을 사용하여 .decode() 함수를 호출한다. 

아래는 express-jwt 모듈을 사용한 코드이다.


auth.js

'use strict'; 

var jwt = require('jsonwebtoken'); 
var compose = require('composable-middleware'); 
var SECRET = 'token_secret'; 
var EXPIRES = 60; // 1 hour 

// jwt에서 사용한 시크릿 문자열과 동일한 문자열로 객체 생성 
var validateJwt = require('express-jwt')({secret: SECRET}); 

function isAuthenticated() { 
  return compose() 
      // Validate jwt 
      .use(function(req, res, next) { 
        // 만약 access_token 파라메터에 토큰을 설정한 경우 리퀘슽 헤더에 토큰을 설정한다. 
        if(req.query && req.query.hasOwnProperty('access_token')) { 
          req.headers.authorization = 'Bearer ' + req.query.access_token; 
        } 

        // 토큰 인증 로직 
        validateJwt(req, res, next); 
      }) 
      // Attach user to request 
      .use(function(req, res, next) { 
        req.user = { 
          id: req.user.id, 
          name: 'name of ' + req.user.id 
        }; 
        next(); 
      }); 

}

참고사이트

http://webframeworks.kr/tutorials/expressjs/auth_log_in_out/

'do > nodejs' 카테고리의 다른 글

Redis  (0) 2019.04.08
Request, Response  (0) 2019.04.07
dotenv  (0) 2019.04.05
Swagger  (1) 2019.04.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함