블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

REST JWT(JSON Web Token)소개 - #2 node.js에서 JWT 사용하기

조대협 (http://bcho.tistory.com)


Jwt-simple을 이용한 node.js에서 JWT 토큰 사용하기

앞에서 http://bcho.tistory.com/999 JWT 토큰에 대한 개념에 대해서 간략하게 알아보았다. 그러면,실제로 JWT 토큰을 어떻게 생성하고 파싱하는 지를 node.js를 샘플을 통해서 알아보도록 하자.

시작부터 말하자면. 너무 쉽다. 쉬워도 너무..!!

node.js에는 여러가지 JWT 라이브러리가 있지만 그중에서 가장 사용이 편리한 라이브러리는 jwt-simple 이라는 라이브러리가 있다. 먼저 npm을 이용해서 해당 패키지를 설치한 후에

 


<그림. npm을 이용하여, jwt-simple 모듈을 설치>

다음과 같은 코드를 작성한다.

var jwt = require('jwt-simple');

var body= { name:'terry.cho',id:'terry',company:'coca'}

var secret ='mysecret';


var token = jwt.encode(body,secret);

console.log('token :'+token);


var decoded = jwt.decode(token,secret);

console.log('decoded:'+JSON.stringify(decoded));


위의 코드에서 body에 해당하는 부분이 JWT 토큰안에 들어갈 실제 claim이다. 그리고 secret은 HMAC-SHA1-256 을 생성하기 위한 비밀 키로, jwt.encode에 이 claim JSON과, secret을 주면, token이 생성된다.

반대로, decode에 encoding된 토큰과 secret을 인자로 넘겨주면 claim을 디코딩할 수 있다.

 


<그림. 예제 실행 결과>

디폴트로 HMAC-SHA1256 (HS256이라고 함)을 지원하며, HS384,HS512와 RS256도 지원한다.

자바,파이썬등의 JWT 라이브러리

그외에 다른 프로그래밍 언어에도 여러가지 JWT 라이브러리가 제공된다. 아래는 Atlassian 홈페이지에서 참고한 JWT 라이브러리 목록이다.

Language

Library

Java

atlassian-jwt and jsontoken

Python

pyjwt

Node.js

node-jwt-simple

Ruby

ruby-jwt

PHP

firebase php-jwt and luciferous jwt

.NET

jwt

Haskell

haskell-jwt


<그림. 다른 프로그래밍 언어의 JWT 라이브러리>

※ 출처 : https://developer.atlassian.com/static/connect/docs/concepts/understanding-jwt.html

이외에도 http://jwt.io/ 사이트에 가면, 각종 언어에 대한 JWT 라이브러리를 제공한다.


문제점

사용이 쉽고, 서버의 개발 부담을 덜어줄 수 있다는 여러가지 장점을 가지고 있으나, 그만큼 또 단점도 가지고 있다.


길이

Claim에 넣는 데이터가 많아질 수 록, JWT 토큰의 길이가 길어진다. API 호출등에 사용할 시에,매 호출마다 헤더에 붙어서 가야하기 때문에, 길이가 길다는 것은 그만큼 네트워크 대역폭 낭비가 심하다는 의미이다.


한번 발급된 토큰은 값을 수정하거나 폐기가 불가

JWT는 토큰 내에 모든 정보를 다 가지고 있기 때문에, 한번 발급된 토큰에 대한 변경은 서버에서는 더 이상 불가능하다. 예를 들어 토큰을 잘못 발행해서 삭제하고 싶더라도, Signature만 맞으면 맞는 토큰으로 인식을 하기 때문에, 서버에서는 한번 발급된 토큰의 정보를 바꾸는 일등이 불가능하다.

그래서 만약에 JWT를 쓴다면, Expire time을 꼭 명시적으로 두도록 하고, refresh token등을 이용해서, 중간중간 토큰을 재발행하도록 해야 한다. (하루 단위 정도?) 


보안

JWT는 기본적으로 Claim에 대한 정보를 암호화 하지 않는다. 단순히 BASE64로 인코딩만 하기 때문에, 중간에 패킷을 가로채거나, 기타 방법으로 토큰을 취득했으면 토큰 내부 정보를 통해서 사용자 정보가 누출 될 수 있는 가능성이 있다. 특히 자바스크립트 기반의 웹 클라이언트의 경우 브라우져상의 디버거등을 통해서 토큰이 노출될 가능성이 높다.

그래서, 이를 보완하는 방법으로는 토큰 자체를 암호화 하는 방법이 있다. JSON을 암호화 하기 위한 스펙으로는 JWE(JSON Web Encryption)


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 류재영 2015.04.02 16:04  댓글주소  수정/삭제  댓글쓰기

    너무 잘보고 갑니다.
    보안에 대해서 좀 더 고찰을 해봐야겠네요.
    퍼갑니다.

  2. front 2018.05.25 11:33  댓글주소  수정/삭제  댓글쓰기

    한번 발급한 토큰에 대해 폐기가 불가능한 점 클라이언트에서 로그아웃 처리를 해도 의미가 없는거같은데 별도의 저장소를 갖는 것 외에 다른 해결방법은 없을까요..?

  3. gwise 2019.03.23 22:54  댓글주소  수정/삭제  댓글쓰기

    한번 발급된 토큰 폐기/불능(?)으로 만들 수 있습니다.
    발급할때 사용한 HMAC256 Key값을 바꾸고 was 재시작하면 verifier 할때 이전에 정상 토큰 갖고 있어도 리젝 됩니다.
    RSA 방식으로 사용하면 인증서버 was만 재시작해도 이전 토큰 발급된거 리젝되고..
    JWT관련 한글 관련 자료 보면 위와 같이 잘못된 내용이 있어 덧글 남기고 갑니다.

JWT(JSON Web Token)을 이용한 API 인증 - #1 개념 소개

조대협 (http://bcho.tistory.com)


REST API에 대한 보안과 인증이 화두가 되면서 많이 언급되는 것이 OAuth인데, 근래에 들어서 화두가 되고 있는 것이 JWT (JSON Web Token)이라는 표준이다.


Claim기반 토큰의 개념


OAuth에 의해서 발급되는 access_token은 random string으로 토큰 자체에는 특별한 정보를 가지고 있지 않는 일반적인 스트링 형태 이다. 아래는 페이스북에서 발급된 access_token의 형태로 일반적인 문자열 형태임을 확인할 수 있다.



<그림1.  Facebook의 Oauth에서 사용하는 일반적인 스트링 기반 토큰 예제>

 

 API나 서비스를 제공하는 서버 입장에서 그 access_token을 통해서 사용자에 연관된 권한(예를 들어 scope같은 것)을 식별한 뒤 권한을 허용해주는 구조이다.

즉 서비스를 제공하는 입장에서는 토큰을 가지고 그 토큰과 연관된 정보를 서버쪽에서 찾아야 한다. (사용자 ID나 권한등).

JWT는 Claim 기반이라는 방식을 사용하는데, Claim이라는 사용자에 대한 프로퍼티나 속성을 이야기 한다. 토큰자체가 정보를 가지고 있는 방식인데, JWT는 이 Claim을 JSON을 이용해서 정의한다.

다음은 Claim을 JSON으로 서술한 예이다.이 JSON 자체를 토큰으로 사용하는 것이 Claim 기반의 토큰 방식이다.

{

  "id":"terry"

  ,"role":["admin","user"]

  ,"company":"pepsi"

}

<코드 1. JSON으로 Claim을 기술한 토큰의 형태 >

자 그렇다면, 이러한 Claim 방식의 토큰은 무엇이 좋을까? 이 토큰을 이용해서 요청을 받는 서버나 서비스 입장에서는 이 서비스를 호출한 사용자에 대한 추가 정보는 이미 토큰안에 다 들어가 있기 때문에 다른 곳에서 가져올 필요가 없다는 것이다.

“사용자 관리” 라는 API 서비스가 있다고 가정하다.

 이 API는 “관리자(admin)” 권한을 가지고 있는 사용자만이 접근이 가능하며, “관리자” 권한을 가지고 있는 사용자는 그 관리자가 속해 있는 “회사(company)”의 사용자 정보만 관리할 수 있다. 라고 정의하자

이  시나리오에 대해서 일반적인 스트링 기반의 토큰과 JWT와 같은 Claim 기반의 토큰이 어떤 차이를 가질 수 있는 지 알아보도록 하자.


OAuth 토큰의 경우



<그림 2. String 토큰에 의한 API 권한 인증 흐름>

 

1.    API 클라이언트가 Authorization Server (토큰 발급서버)로 토큰을 요청한다.

이때, 토큰 발급을 요청하는 사용자의 계정과 비밀번호를 넘기고, 이와 함께 토큰의 권한(용도)을 요청한다. 여기서는 일반 사용자 권한(enduser)과 관리자 권한(admin)을 같이 요청하였다.

2.    토큰 생성 요청을 받은 Authorization Server는 사용자 계정을 확인한 후, 이 사용자에게 요청된 권한을 부여해도 되는지 계정 시스템등에 물어본 후, 사용자에게 해당 토큰을 발급이 가능하면 토큰을 발급하고, 토큰에 대한 정보를 내부(토큰 저장소)에 저장해놓는다.

3.    이렇게 생성된 토큰은 API 클라이언트로 저장된다.

4.    API 클라이언트는 API를 호출할때 이 토큰을 이용해서 Resource Server(API 서버)에 있는 API를 호출한다.

5.    이때 호출되는 API는 관리자 권한을 가지고 있어야 사용할 수 있기 때문에, Resource Server가 토큰 저장소에서 토큰에 관련된 사용자 계정, 권한 등의 정보를 가지고 온다. 이 토큰에 (관리자)admin 권한이 부여되어 있기 때문에, API 호출을 허용한다. 위에 정의한 시나리오에서는 그 사용자가 속한 “회사”의 사용자 정보만 조회할 수 있다. 라는 전제 조건을 가지고 있기 때문에, API 서버는 추가로 사용자 데이타 베이스에서 이 사용자가 속한 “회사” 정보를 찾아와야한다.

6.    API서버는 응답을 보낸다.


JWT와 같은 Claim 기반의 토큰 흐름을 보자

 



<그림 3. Claim 기반의 토큰을 이용한 API 권한 인증 흐름 >

 

1.    토큰을 생성 요청하는 방식은 동일하다.  마찬가지로 사용자를 인증한다음에, 토큰을 생성한다.

2.    다른 점은 생성된 토큰에 관련된 정보를 별도로 저장하지 않는다는 것이다. 토큰에 연관되는 사용자 정보나 권한등을 토큰 자체에 넣어서 저장한다.

3.    API를 호출하는 방식도 동일하다.

4.    Resource Server (API 서버)는 토큰 내에 들어 있는 사용자 정보를 가지고 권한 인가 처리를 하고 결과를 리턴한다.

결과적으로 차이점은 토큰을 생성하는 단계에서는 생성된 토큰을 별도로 서버에서 유지할 필요가 없으며

토큰을 사용하는 API 서버 입장에서는 API 요청을 검증하기 위해서 토큰을 가지고 사용자 정보를 별도로 계정 시스템 등에서 조회할 필요가 없다는 것이다.


참고 : 다른 Claim 기반 토큰은?


그러면 이러한 Claim 기반의 토큰이 JSON이 처음일까? 이미 이전에, XML기반의 SAML 2.0이 이와 비슷한 개념을 가지고 있다. Assertion이라는 개념으로 XML안에 이러한 Claim 정보를 넣어서 넘길 수 있었으나, 문제점은 전체적인 사이즈가 너무 크고, 구조가 복잡하여 쉽게 접근이 어려웠다. 더군다가 크기가 크기 때문에 API와 같이 자주 호출해야 하는 경우에는 HTTP 헤더등에 실어서 보내기가 어렵고, 파싱에 대한 오버해드가 크기 때문에 적절하지 않았다. (주로 다른 사이트나 시스템간의 SSO에서 상호 사용자 인증등을 위해서 사용된다. 무겁기는 하지만 표준화가 잘되어 있기 때문에 사용자 인증 시나리오에서는 현재에도 많이 사용된다.)

JWT는 이JSON Claim을 BASE64로 인코딩하여HTTP Header에 쉽게 넣을 수 있으며, JSON 기반이기 때문에 파싱과 사용이 쉽다.

결과적으로 Claim 기반의 토큰은 토큰 자체가 정보를 담음으로써, 토큰을 가지고 서비스나 API 접근을 제어할 때 별도의 작업이 서버에서 필요하지 않으며, 토큰 자체를 서버에서 관리할 필요가 없기 때문에 구현이 상대적으로 단순해진다.


JWT에 대한 소개


Claim 기반의 토큰에 대한 개념을 대략적으로 이해했다면, 그러면 실제로 JWT가 어떻게 구성되는지에 대해서 살펴보도록 하자.


Claim (메세지) 정의

JWT는 Claim을 JSON형태로 표현하는 것인데, JSON은 “\n”등 개행문자가 있기 때문에, REST API 호출시 HTTP Header등에 넣기가 매우 불편하다. 그래서, JWT에서는 이 Claim JSON 문자열을 BASE64 인코딩을 통해서 하나의 문자열로 변환한다.

{

  "id":"terry"

  ,"role":["admin","user"]

  ,"company":"pepsi"

}

<코드 2. JSON 기반의Claim 예제>

문자열을 BASE64 인코딩 한 결과

ew0KICAiaWQiOiJ0ZXJyeSINCiAgLCJyb2xlIjpbImFkbWluIiwidXNlciJdDQogICwiY29tcGFueSI6InBlcHNpIg0KfQ0K

<코드 3. JSON 기반의 Claim 코드 2를 BASE64 인코딩 한 결과>


변조 방지

위의 Claim 기반의 토큰을 봤으면, 첫번째 들 수 있는 의문이 토큰을 받은 다음에 누군가 토큰을 변조해서 사용한다면 어떻게 막느냐? 이다. 이렇게 메세지가 변조 되지 않았음을 증명하는 것을 무결성(Integrity)라고 하는데, 무결성을 보장하는 방법중 많이 사용되는 방법이 서명(Signature)이나 HMAC 사용하는 방식이다. 즉 원본 메세지에서 해쉬값을 추출한 후, 이를 비밀 키를 이용해서 복호화 시켜서 토큰의 뒤에 붙인다. 이게 HMAC방식인데,  누군가 이 메세지를 변조를 했다면,변조된 메세지에서 생성한 해쉬값과 토큰뒤에 붙어 있는 HMAC값이 다르기 때문에 메세지가 변조되었음을 알 수 있다. 다른 누군가가 메세지를 변조한후에, 새롭게 HMAC값을 만들어내려고 하더라도, HAMC은 앞의 비밀키를 이용해서 복호화 되었기 때문에, 이 비밀키를 알 수 없는 이상 HMAC을 만들어 낼 수 없다.


※ HMAC에 대한 자세한 설명은http://bcho.tistory.com/807 를 참고하기 바란다.

그래서 앞의 JSON 메세지에 대해서 SHA-256이라는 알고리즘을 이용해서 비밀키를 “secret” 이라고 하고, HMAC을 생성하면 결과는 다음과 같다.

i22mRxfSB5gt0rLbtrogxbKj5aZmpYh7lA82HO1Di0E

<코드 4. 코드 2의 JSON기반 Claim에 대해서, SHA1-256으로 생성한 HMAC>

서명 생성 방식

그러면 무결성 보장을 위해서 사용할 수 있는 알고리즘이 SHA1-256 HMAC 뿐일까? 보안요건에 따라서 SHA1-256,384,512. 그리고 공인 인증서 (Ceritification)을 이용한 RS256 등등 다양한 서명 방식을 지원한다. 그렇다면 JWT 토큰이 어떤 방식으로 서명이 되어 있는지는 어떻게 알 수 있을까?

그래서 JWT 토큰의 맨 앞부분에는 서명에 어떤 알고리즘을 사용했는지를 JSON형태로 정의한후, 이 JSON을 다시 BASE64 방식으로 인코딩한 문자열을 붙인다

{"alg":"HS256","typ":"JWT"}

<코드 5. JSON으로 서명 생성 방식은 SHA1-256으로 정의한 예>

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

<코드 6. 위의 코드 5 JSON 문자열을 BASE64 인코딩한 결과>

 

전체 메세지 포맷


위에서 설명한, 서명 방식, JSON 기반의 Claim,그리고 서명(Signature)까지 포함된 전체적인 JWT 토큰의 구조를 보면 다음과 같다.

{서명 방식을 정의한 JSON을 BASE64 인코딩}.{JSON Claim을 BASE64 인코딩}.{JSON Claim에 대한 서명}

이를 정리해서 그림으로 서술해 보면 다음과 같다.


<그림. JWT 토큰 구조>

그리고 결과로 나온, JWT 토큰은

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ew0KICAiaWQiOiJ0ZXJyeSINCiAgLCJyb2xlIjpbImFkbWluIiwidXNlciJdDQogICwiY29tcGFueSI6InBlcHNpIg0KfQ0K.i22mRxfSB5gt0rLbtrogxbKj5aZmpYh7lA82HO1Di0E

가 된다.


2편에서 다룰 내용

  • 유출 방지(암호화)

  • 상세 스펙

  • 구현예제


 

 

 

 

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. spike 2015.01.31 08:15  댓글주소  수정/삭제  댓글쓰기

    매우 좋은 글입니다. API 서비스 인증 토큰을 구현하는데 많은 참고가 되겠습니다.
    다음 글에서 Secured Channel 을 통한 통신에 관해서도 다뤄 주시면 더 좋을 것 같습니다.

  2. cdy 2015.03.19 09:24  댓글주소  수정/삭제  댓글쓰기

    항상 좋은글 친절한 설명 잘보고 있습니다.
    해당 내용도 확인 했는데 의문점은 JWT 토큰 자체를 만약 해커가 알게되면 다른 USER로 접근이 언제든지 가능해 보입니다.
    Caim Json 부분에 시간타임을 넣어 유효한지 체크하는 로직을 자유롭게 처리해도 되는건가요?
    ( 죄송합니다. 스팩을 아직 못봐서 )

    • 조대협 2015.03.19 13:57 신고  댓글주소  수정/삭제

      토큰 노출 되면 끝이져...
      말씀하신데로, replay attack등을 방어하기 위해서 timestamp를 넣는 것도 좋은 방법이 됩니다만 서버에서 토큰을 만들어서 내리는 방법이 일반적이라서, 이 경우 토큰을 자주 내려야 합니다.

      아니면 클라이언트가 토큰을 만든 후 싸이닝을 하기 위한 shared key를 가지고 있어야 하는데, 키를 클라이언트에 넣어놓는게 그리 좋은 방법이 아니라서 권장하기가 어렵네요.

  3. tonkey 2015.07.03 17:11  댓글주소  수정/삭제  댓글쓰기

    jwt 를 java 구현예제가 좀 있을까요? jwt 라이브러리 예제도 좋고요...특히 createJwt 와 거꾸로 verify 부분 예제요.

  4. 손명우 2015.08.04 08:28  댓글주소  수정/삭제  댓글쓰기

    글 잘읽었습니다.
    궁금한게 좀 있는데요.
    현재 하이브리드앱 개발중에 있습니다.
    토큰값을 받아와서 localstorage에 저정해서 써도되나요? 한번 로그인하면 다음부터는 자동로그인을 적용해야돼서요..^^

  5. 호러블캣 2015.11.02 17:58  댓글주소  수정/삭제  댓글쓰기

    알기 쉽게 설명해 주셔서 감사합니다, 많은 도움이 되었습니다~!

  6. 박종빈 2016.01.28 09:16  댓글주소  수정/삭제  댓글쓰기

    페이로드 뿐만 아니라 헤더까지 포함시켜 HMAC 서명을 하는 것으로 알고 있었는데, 한 번 확인해주실 수 있으신지요.

  7. 어떻게. 2016.02.08 01:15  댓글주소  수정/삭제  댓글쓰기

    언제나 잘 보고 갑니다!^^ 책을 사서 보고 있는데여. 궁금한 점이 있습니다.
    책에서 JWT를 쓴다면 만료시간을 꼭 명시적으로 두도록 하고 중간마다 토큰을 재 발행하도록 권장하시고 계시는데여.
    그러면 초기에 토큰을 발행할때 만료시간을 주고 그것을 클라이언트한테 넘기고, 클라이언트가 api 호출할때 토큰을 받아 항상 만료 시간을
    검사해서 만료시간이 지나지 않았다며? 시간을 늘려서 다시 토큰을 만들고 API 서버에서 새로운 토큰을 클라이언트한테 전달하라는 말씀인지여? 토큰 재발행에 대한 로직이 잘 이해가 가지 않습니다!!^^ 제가 아직 많이 몰라서여... 감사합니다.

    • 조대협 2016.02.08 01:29 신고  댓글주소  수정/삭제

      클라이언트가 토큰의 만료시간을 알 수 있기 때문에, 클라이언트에서 판단해서 만료시간이 넘었으면 토큰 재발급을 요청하는게 가장 일반적인 방법이 아닐까 합니다.

  8. goohooh 2016.07.26 19:24  댓글주소  수정/삭제  댓글쓰기

    항상 좋은글 감사합니다!! 다음 글들도 기대하겠습니다!!

  9. 푸름 2016.12.22 18:26  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 처음 방문했어요 좋은정보 감사드려서 댓글 달고 가요! 정말 감사합니다. 선배님 같은 분들이 계셔서 후배들은 빠르고 쉽게 배우고가요~! ㅎㅎ 감사합니다. 자주 구독하러 방문할께요!

  10. keichee 2017.03.31 10:03  댓글주소  수정/삭제  댓글쓰기

    이것저것 검색하다보면 항상 여기로 들어오는 것 같네요. 그리고 드어올때마다 감탄합니다. 정리를 너무 잘 해 놓으셔서요. 좋은 글 계속 읽을 수 있으면 좋겠습니다. 감사합니다~ ^-^

  11. anywon 2017.05.24 00:42  댓글주소  수정/삭제  댓글쓰기

    좋은 자료 감사합니다.
    한가지 질문이 있습니다.
    "즉 원본 메세지에서 해쉬값을 추출한 후, 이를 비밀 키를 이용해서 복호화 시켜서 토큰의 뒤에 붙인다."
    라는 문구에서 복호화 시켜서 토큰의 뒤에 붙인다 라는 것이 이해가 되지 않습니다.
    암호화가 아니라 왜 복호화 인지 설명 부탁드립니다..

  12. henryf 2017.09.08 07:57  댓글주소  수정/삭제  댓글쓰기

    보안관련 프로젝트 진행중 자료를 찾다가 이 곳에 방문하게 되었습니다.
    유명하신 조대협님의 블로그는 그간 잘 읽고 있었습니다~^^

    먼저 상세하고 좋은 강좌 감사히 잘 읽었습니다.

    아직 jwt 에 대해 공부중이라 잘 몰라서 하는 질문이니 미리 양해 말씀 드립니다.


    1. 서버에서 발급한 키를 클라이언트가 다음 요청을 위해서 키를 보관후 보내야 하는데 이 경우 키는 쿠키 나 웹스토리지 외에 어디에 저장해야 하는지요?
    (다른 곳에서 읽은 내용입니다만 jwt 가 쿠키베이스 인증방식보다 낫다는 내용이 있어서요)

    2. 사용자의 pc내 쿠키나 네트웍에서 해당키가 전송되는걸 도청해서 동일키를 다른 곳이서 보낸다면 서버는 역시나 같은 클라이언트로 인식할것입니다. 쿠키조회나 네트웍 도청이 가능하다는 가정에서는 공격자가 "정보 수집후 재전송" 에는 동일한 문제점으로 보입니다.

    3. 그냥 클라이언트가 아이디 암호 보내고 서버가 해당 아이디의 db에 저장된 암호 비교 하는 방식에 비해 다를게 없어 보입니다. 공격자가 암호 부분 수정 없이 아이디 영역에 다른 아이디 넣어 보낸들 의미가 없으니..

    2 3 내용으로 보면 아이디암호 읽기쉽게 보내나 읽기어렵게 뭉쳐서 보내나의 차이인데 공격자가 카피해 보낼 수 있다면 이는 보안에 별 도움이 안 될듯 느껴집니다.

    4. 서버는 아이디, 암호, 임시암호, 임시암호 유효기간을 db에 저장하고 클라이언트는 아이디, 암호로 발급받은 임시암호, 유효기간을 쿠키로 저장후 상황따라 일반 텍스트로 보내고 서버가 db 조회후 처리하는 것과 비교해 보안적으로 어떤 장점이 있는지 궁금합니다. 이 임시암호가 123 인지 복잡한 영문자 100 자리인지는 중요치 않다고 봅니다.

    4번 방식은 jwt 에 비해 한 작업당 사용자 검증을 위한 db조회 1회 더 하는 모양이지만 이후 서비스를 위해 어차피 db 작업을 해야하는 상황에선 큰 잇점으로 느껴지지 않습니다.
    (더욱이 jwt에는 서버에 등록된 적합한 아이디라는 증빙만 있을뿐 해당 작업을 수행 할 수 있는 권한을 알기 위해선 결국 서버 db를 조회해야 하니까요.. 작업당 jwt를 발급하는 것은 현실적으로 어려울듯하고..)

    jwt 는 토큰만 보고는 사용자 아이디를 알 수 없다는 장점은 있어 보입니다만 현실적으로 토큰을 이용해서 서비스 요청하다면 제공되는 화면을 보고 결국 사용자 아이디를 알게 될 확율은 높을듯 합니다.

    다만 저장된 사용자 정보가 굉장히 많으면 아이디 암호 임시암호 조회에 db 부하가 걸리니 jwt가 잇점이 될듯합니다.

    반대로 jwt는 헤더가 길어지고 각 작업당 jwt 디코딩을 위한 cpu 부하가 생길듯 합니다.

    성능을 떠나 제 좁은 소견으론 jwt가 서버 db 저장된 암호+임시암호 방식에 비해서 보안적으로 장점을 못 느끼겠습니다.
    그냥 사용자 인증만 되면 모든 작업을 다 할 수 있는 환경이나 권한 지정이 아주 간단한 경우가 아니라면 말이죠..

    프로젝트 중에 급히 고민하는 중이고 강좌의 jwt 내용에 대한 이해도 부족해서 제가 잘못 이해하고 있는 부분이 많습니다.

    미리 사과 말씀 드리며 고견을 기다리겠습니다.

    어렵게 공부하신 지식을 공유해 주심에 감사 말씀 드립니다.

    • dunga 2017.09.26 12:36  댓글주소  수정/삭제

      작성자는 아니고 저도 공부하는 입장에서 제가 아는 범위 내에서 답변하면..

      1. 앱 정책에 따라 다르지 않겠습니까? 언제 세션이 파기되어야 하는지에 따라 localStorage, sessionStorage 를 적당히 결정하면 될 거 같습니다.

      2. 아이디와 비밀번호가 노출되는 거와 마찬가지 같습니다. 하이재킹을 막고 싶으시다면 https를 보는게 어떨까요?

      3. 토큰 인증 방식을 사용하는 이유는 보안을 강화하기 위한 목적이 아님으로 압니다.
      아이디와 암호를 보내는 방식은 서버가 매번 DB 자원을 소모해야 합니다.

      4. 다시 한 번 말하지만 보안 측면에서 접근하는 것은 잘못 되었다고 생각합니다.

      왜 기존 세션 관리 방식인 Stateful 에서 토큰 인증 방식인 Stateless로 대세가 되는지 아셔야 할 거 같습니다. 보안 문제가 아닌 다양한 디바이스가 생겨나고 이 디바이스들을 대처하기 위해서죠.

      세션 관리 방식을 사용 했다면 사용자는 하나지만 디바이스마다 세션을 관리해야 하죠?

      CPU 부하가 온다고 하셨지만 그래서 해시 알고리즘을 썼습니다. 복호화가 아니라 해시가 일치하는지 비교하는 거 아닌가요?

      ID, PWD를 매번 비교하기 위해서 DB 자원을 소모하는 것보다는 훨씬 이득이라고 생각합니다.

      토큰만 보고 사용자 아이디를 알 수 없다고 하셨는데, 인코딩 된 문자열을 보고 단순하게 말씀하신 것이 맞나요? 아니라면 암호화가 아닌 인코딩이기 때문에 바로 알 수 있습니다. 절대 민감 정보는 토큰에 저장해선 안됩니다.

  13. ehdvudee 2018.04.26 11:30  댓글주소  수정/삭제  댓글쓰기

    일단 HMAC 관련 설명이 틀려서 정정 해드려요. 영문 위키 들어가면 잘 설명 되어있는데, HMAC은 일단 key를 i 패딩한 값과 메시지를 한번 해쉬를 하고, 그 해쉬를 key o 패드 한 것을 합쳐서 또 한번 해쉬를 합니다.

  14. ehdvudee 2018.04.26 11:33  댓글주소  수정/삭제  댓글쓰기

    그리고 굳이 집자면은, 서명의 목적은 부인방지 입니다. MAC은 메시지의 무결성 입증은 맞지만, 서명은 부인방지의 목적을 위해 사용합니다.

  15. question 2018.05.23 14:08  댓글주소  수정/삭제  댓글쓰기

    jwt관련 정보를 여기저기에서 찾다가 위 글을 읽게되었습니다. 개인적으로 위 글을 읽고 공부가 많이 되었고 계속 읽고 있습니다.
    궁굼한 점은 jwt를 공부하고 구현하면서 jwt는 jwt.io에서 쉽게 복호화(?)를 할 수 있어 payload를 쉽게 볼 수 있지 않을까 라는 생각이 들었습니다. 그래서 어떻게 payload를 어떻게 해서 클라이어트에 보내줘야 하는지 궁굼증이 생겼습니다. 혹시 시간이 있으시면 제 질문에 답변해 주시면 감사하겠습니다.

  16. 먹튀 검증 2018.08.07 14:18  댓글주소  수정/삭제  댓글쓰기

    관리자의 승인을 기다리고 있는 댓글입니다

  17. skyer9 2019.01.28 21:17  댓글주소  수정/삭제  댓글쓰기

    jwt 는 보안 취약점을 일부 감수하고 DB 자원을 아끼기 위한 방법입니다.
    토큰을 중간에 절취 당하지 않기위해 https 가 필수이고
    그럼에도 핸드폰이 다른 사람 손에 들어가는 상황까지 고려해야 하고요.
    해커에 의해 토큰이 설치된 상황을 대응하기 위해 기기 로그인 아이피 등을 토큰에 넣는것도 방법이 되겠죠.