티스토리 뷰



Node.js 애플리케이션에서 JWT를 이용한 토큰 인증을 구현해보려고 합니다!!

토큰 인증 절차는 다음과 같습니다.

사용자가 로그인을 진행할 때! 사용자 정보로 토큰 정보를 생성하여 저장하고, 이 토큰을 이용하여, 사용자 인증을 필요로 하는 부분을 대체하는 것입니다.

기존에 가장 쉬운 세션에 사용자 로그인 후 정보를 담아두고 하는 것은 보안에 취약하기 때문에, 그보다는 토큰 방식의 사용자 인증 방식이 좋습니다.

자세한 것은 토큰 인증 방식에 대해서 검색하시면 내용이 많이 있어요!!

책을 보면서 하고 있는데 소스 자체는 MIT 라이센스 이니 소스를 보면서 하도록 하겠습니다~~~!

(소스 출처는 scotch.io 라는 외국 사이트에 MEAN Stack beginner 책에 대한 소스 코드입니다.)

먼저, Node.js 에서 JWT를 사용하려면 모듈을 필요로 하니 모듈을 받도록 하겠습니다.

package.json 에 dependencies 에 입력후 npm install 을 해주시거나 직접

npm install jsonwebtoken --save 명령어를 통해 설치후 자동으로 package.json에 작성되도록 하는 방법도 있습니다.

이렇게 먼저 프로젝트 폴더 안에 node_modules/jsonwebtoken/* 이 생기도록 설치해주세요.

영어 도서라.. 영문도 섞여있고.. 한글도 섞여 있음을 양해해주세요 ㅠ_ㅠ

먼저, Node.js 애플리케이션의 서버 설정 파일인 server.js 에 모듈을 추가해야합니다.


// Token Authentication var jwt = require('jsonwebtoken'); var secretKey = 'ilikewoobongwoobongwoobong';

secretKey는 토큰 생성할 때 추가하는 서버만의 Key 이니 독특하게 생성하시며 될 것 같습니다.

// express 라우터의 인스턴스 저장 var apiRouter = express.Router();

// 토큰 생성 apiRouter.post('/authenticate', function(req, res) { User.findOne({username : req.body.username}).select('name username password').exec(function(err, user){ if ( err ) throw err; // 유저가 존재하지 않을 때 if ( !user ) { res.json({ success : false, message : '인증 실패 - 사용자가 존재하지 않음'}); } else if ( user ) { // 유저가 존재할 때 var validPassword = user.comparePassword(req.body.password); if ( !validPassword ) { res.json({ success : false, meesage : '인증 실패 - 비밀번호 확인'}); } else { // 사용자 정보가 일치하면, 토큰 생성 var token = jwt.sign({ name : user.name, username : user.username }, superSecret, { expiresInMinutes : 1440 // 만기 시간 24시간 }); // 토큰 정보 반환 res.json({ success : true, message : '토큰을 받고 즐기시오~!!', token : token }); } } }); }); // 인증 확인 부분 apiRouter.use(function (req, res, next) { var token = req.body.token || req.param('token') || req.headers['x-access-token']; if (token){ jwt.verify(token, superSecret, function(err, decoded) { if ( err ) { return res.status(403).send({ success : false, message : '토큰 인증 실패.'}); } else { req.decoded = decoded; next(); } }); } else { return res.status(403).send({success : false, message : '인증 토큰이 없습니다.'}); } });

라우팅 개념은 알고 계셔야 합니다.

저도 공부하는 입장에서 이렇다 자세히 설명을 드릴 수는 없지만~ 라우팅은 이제 서버에 접속하는 URL을 컨트롤 하는 것이라고 보시면 됩니다. HTTP Method 등을 관리할 수 잇죱

지금 apiRouter는 express의 인스턴스를 저장했으므로, 라우팅을 할 수 있는 인스턴스가 되었고, 위에는 인증부분만 적어놓은 것입니다.

실제로 /users URL로 GET, POST 로 각각 유저 정보 리스트, 유저 정보 입력 을 구현해 두었습니다.

API 서비스 형식으로 RESTful 하게 진행되는 예제 입니다. 

apiRouter의 URL은 /api/ 로 시작하고, /api/authenticate 를 통해 인증 토큰을 생성할 수 있습니다.

주의할 점은 인증 부분의 토큰 생성 부분이 인증 확인 부분보다 위에 있어야 한다는 점입니다

안 그러면, 인증 토큰이 없습니다..라는 메세지를 계속 받으실 수 있어요 ^^;;; ㄷㄷ

소스에서 보면 User.findOne() 의 메소드를 사용하는데.. 음...이 부분은 제가 mongoDB를 사용하고 있어서,

mongoose Schema 형태로 User를 생성해 두었습니다 ( 위에서 말씀드린 사이트에서 전체 소스를 찾아서 보세요 )

위 처럼 구현을 한뒤 아래 이미지 처럼 (postman 을 통해 데이터 전달 Client 부분이 구현이 안되있어요~) 데이터를 전송합니다. ( 로그인이라고 보시면 되요 )

소스 코드를 비롯하여 설명하면 먼저!

User 정보를 db에서 찾아서 조회를 합니다. 그리고 정보인 name, username, password를 읽어오죠!

User정보가 없으면 유저가 없다고 실패 메세지를 전달하고, 유저가 존재하면, 암호 확인을 합니다. 암호 또한 암호화가 되어 있기 때문에~ comparePassword()라는 메소드를 사용하고 있어요..

이제 암호도 확인이 되면, 토큰을 생성합니다!!

var token = jwt.sign( ... ) * 모듈에 대한 설명 ( https://github.com/auth0/node-jsonwebtoken )

jwt.sign(payload, secretOrPrivateKey, options) 

들어가는 내용은 sign({name : user.name, username : user.username}, secertKey, { expiresInMinutes : 1440 }); 입니다.
payload는 앞 게시물에서 설명한 것처럼, 일반적으로 사용자가 정의하는 정보를 담는 공간입니다~
여기서는 사용자의 정보를 담겠죠~ secretOrPrivateKey는 서버에서 가지는 secertKey 위에서 선언한 부분이고
Option은 많은 내용이 있지만 여기서는 토큰이 만료되는 시간만 있네요~ 1440분으로 24시간입니다.
자세한 옵션은 위에 깃허브 URL에서 모듈 설명으로 보실수 있습니다.
이제 제 정보로 토큰을 받았습니다!! 위 이미지 처럼 token 이라는 부분이 있죱~!!

인증 부분도 소스코드를 보면 쉽게 알 수 있을 것 같습니다.

jwt.verify(token, secretOrPublicKey, [options, callback])

토큰이 존재하는 지 확인한 후에, 해당 토큰을 가지고서 서버에서 인증 확인을 하고, 정상적인 인증 토큰이면 해당하는 url 을 수행하도록 되어있습니다.
apiRouter.use 부분은 apiRouter 에 구현되어 있는 기능들을 수행하기 전에 먼저 실행 되는 부분이라고 보시면 됩니다. 그러니깐 인증부분 보다 아래에 구현되어 있는 apiRouter에 소속된 URL 기능들은 인증 토큰이 꼭 필요한 ( 로그인이 된 ) 상태여야 된다는 것이죠..

유새 유행하는 Facebook 로그인 api 나 트위터 로그인 api 같은 것들도 이러한 방식과 비슷할 거라고 생각합니다.
API 식의 사이트를 구현할 때 Node.js 서버에서 인증하는 방법을 알아보았고~
실제로 JWT를 이용한 방식의 서버 인증 방식은 주요 언어들은 대부분의 라이브러리를 가지고 있는 습니다.
( 참고 : http://jwt.io/ )

이 내용을 활용해서 이 후 애플리케이션들의 인증방식을 토큰 형식으로 구현해야 겠어요~!

정리하는 데 있어서 아직 깔끔하지 못하여 죄송합니다~!! 점점 늘겠쬬.. 정리 팁좀 주세요..ㅠ_ㅠ

참고로 풀 소스는 https://github.com/scotch-io/mean-machine-code/tree/master/10-node-authentication 입니다~!!

댓글