웹앱프로젝트/서버

JWT 란? (JWT vs Session)

Minah Park 2022. 8. 3. 23:05
반응형

참조 : https://www.bezkoder.com/jwt-json-web-token/

1. Authentication 이란?

어떠한 웹사이트를 사용할 때, 계정을 생성하고, 어떠한 특정한 기능을 사용하기위해 로그인하여 접근해야한다. 그러한 action 을 우리는 Authentication 이라고 부른다.

 

2. Session 기반의 Authentication

그렇다면, 어떻게 계정을 인증(authenticate)  할까?

우선, 과거에 가장 많이 사용한 심플한 방법인 Session-based Authentication 을 살펴보자!!

https://www.bezkoder.com/jwt-json-web-token/

위의 사진을 보면서 설명해보자.

1. 사용자가 website에 로그인 
2. Server는 그 사용자에 대한 Session을 생성하여 저장 (in Memory or Database)
3. Server는 브라우저 Cookie 에 저장할 그 ClientSessionId를 return
Server에 있는 그 Session은 만료시간을 가지고 있음. 그 일정 시간이 지난 후, 그 Session은 만료되고 다른 Session을 생성하여 다시 로그인을 해야함

4. 로그인이 된 사Cookie 와 SessionId 의 HTTP Request는 Server로 감
5. Server는 인증을 위해 이 SessionId 와 저장된 Session을 비교한 후에
6. 적절한 Response를 return 함

 

3. Token-based Authentication이 탄생한 이유?

그런데, 우리는 왜 Token-based Authentication 을 많이 사용하는 걸까?

이유는, 우리는 website만 가지고 있는 것이 아니고, 많은 플랫폼들이 존재하기 때문이다!

가정해보자, 우리가 사용하는 website가 Session으로 잘 작동한다고 하자. 어느날, 우리가 Mobile (Navtive Apps) 에 시스템을 구축해야하고 같은 Database를 최신 Web app에 사용해야한다면 우리는 어떻게 해야할까?

우리는 Native App의 사용자를 Session을 기반으로 하는 Authentication로 인증할 수 없다. 왜냐면, Native App 과 비슷한 아이들은 Cookie가 없기 때문이다!!!!

그러면, 우리는 Native App 을 위한 Backend 프로젝트를 다시 빌드 하거나, Native App을 위한 Authentication module 을 새로 구축해야한다. 그래서 탄생 한 것이 Token-based Authentication!!!

이 방법으로, 사용자의 login 상태가 Server에 의해 JWT(JSON Web Token) 으로 encoding 되어져서 Client로 보내질 수 있다. 그래서 요즘 RESTful API들은 이것을 많이 사용한다. 그러니 이제 JWT 의 원리에 대해서 알아보자!!!

 

4. Token-based Authentication의 원리

아래의 사진과 같이 이해하기 간단하다.

JWT의 작동

Session을 생성하는 것 대신에, Server는 로그인한 사용자의 data로부터 JWT를 생성하고 Client 로 보낸다. 그 Client 는 생성된 JWT를 이제부터 저장하고 되고, 그 Client로 부터 오는 모든 Request는 모두 JWT를 (보통은 header에) 붙여서 온다. 그러면 Server는 JWT를 인증하고 Response를 return 해준다. 

https://www.bezkoder.com/jwt-json-web-token/
Client side에 JWT를 저장하는 방법은, 어떤 플랫폼을 사용하느냐에 따라 다른다.

Browser : Local Storage
IOS : Keychain
Android : SharedPreferences

 

JWT의 생성 방법

JWT 의 중요한 3가지

Header
Payload
Signature

                Header             

Header는 질문에 대답한다. 

우리가 어떻게 JWT를 계산할까?

이제, header의 예제를 살펴보자. JSON 객체는 이렇게 생겼다: 

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

 

typ  -  'type', Token의 종류를 나타낸다. 여기서는 of course JWT
alg  -  'algorithm', Token signature 를 생성하기 위한 hash 알고리즘. 알고리즘은 Secret Key를 사용 여기서는, HMAC-SHA256 을 말한다. 

 

                   Payload                  

Payload는 우리가 대답할 수 있게 도와준다.

우리는 JWT에 무엇을 저장하고 싶지?

이제, payload는 이렇게 생겼다.

{
  "userId": "abcd1234",
  "username": "minah",
  "email": "contact@minah.com",
  // standard fields
  "iss": "park, author of minah.com",
  "iat": 4568874212,
  "exp": 4568874212
}
3가지의 저장하는 사용자 항목들 : userId , username, email
Standard Fields (선택):
iss (Issuer) - JWT 발행한사람
iat (Issued at) - JWT가 발행된 시간
exp (Expiration Time) - JWT의 만료 시간

더 많은 저장할 수 있는 항목들: https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields

 

                   Signature                  

위에 정의한 Hash Algorithm 을 사용하는 부분!
const data = Base64UrlEncode(header) + '.' + Base64UrlEncode(payload);
const hashedData = Hash(data, secret);
const signature = Base64UrlEncode(hashedData);

1) Header 와 Payload 를 encode 하고, 그것들을 마침표 ( . ) 로 합친다.

data = '[encdoeHeader].[encodedPayload]'

2) 이제, Header에서 정의한 Hash algorithm 과 secret 문자를 활용해서 데이터의 hash 를 만든다.

3) hash한 결과물은 Signature을 얻기위해 encodeing 한다.

                   Header, Payload, Signature 을 모두 합쳐                   

JWT standard structure 에 Header, Payload, Signature을 모두 합침
const encodedHeader = base64urlEncode(header);
/* Result */
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
const encodedPayload = base64urlEncode(payload);
/* Result */
"eyJ1c2VySWQiOiJhYmNkMTIzNDVnaGlqayIsInVzZXJuYW1lIjoiYmV6a29kZXIiLCJlbWFpbCI6ImNvbnRhY3RAYmV6a29kZXIuY29tIn0"
const data = encodedHeader + "." + encodedPayload;
const hashedData = Hash(data, secret);
const signature = base64urlEncode(hashedData);
/* Result */
"crrCKWNGay10ZYbzNG3e0hfLKbL7ktolT7GqjUMwi3k"
// header.payload.signature
const JWT = encodedHeader + "." + encodedPayload + "." + signature;
/* Result */
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJhYmNkMTIzNDVnaGlqayIsInVzZXJuYW1lIjoiYmV6a29kZXIiLCJlbWFpbCI6ImNvbnRhY3RAYmV6a29kZXIuY29tIn0.5IN4qmZTS3LEaXCisfJQhrSyhSPXEgM1ux-qXsGKacQ"
반응형

5. JWT는 데이터를 secure 하는 방법

JWT 는 데이터를 암호화하여 보호하거나, 감추지 않는다.

단지, JWT를 생성하는 과정이 데이터를 encode하고 hash 할 뿐 암호화 하지 않는다. 그래서, JWT를 Main-in-the-middle attack으로 훔칠 수도있다. 그렇기 때문에 application 은 HTTPS encryption (암호화) 를 가지고 있어야한다.

 

6. Server가 Client 로 부터 JWT를  확인하는 방법

앞전에, Signature를 생성하는데 Secret 문자를 사용했다. 그 Secret 문자는 모든 application마다 유니크하고 안전한 server side에 보관되어 있어야한다.

Client로 부터 JWT를 받았을 때, Server는 Signature를 받아 그 Signature가 같은 알고리즘Secret문자로 hash 되었는지 확인한다. 

 

중요!!
Server로 Payload를 보낼 때, Payload정보는 숙력된 프로그래머들에 의해서 편집이나 추가가 될 수 있다. 

그러면 어째야하냐구?

Token 을 Client로 보내기전에 저장해야한다. 그럼으로써, 나중에 Client로 부터 보내진 JWT가  valid 하다는걸 보장할 수 있다.

또한, 사용자의 Token을 Server에 저장하는 것 또한 시스템으로부터 Force Logout 기능도 도울 것이다.

 

 

 

 

 

참고 사이트를 내 나름대로 번역해서 적은 것이기 때문에, 영어에 능한 사람은 맨위에 있는 참고사이트를 보는 것을 더욱 추천한다! 역시 영어가 더욱 직설적이고 심플하게 표현되다보니 이해하는게 더 쉽다.

반응형