[보안] Session , Token , JWT

# 참고 

[보안] Hash, MD5, SHA

# 참고 : https://galid1.tistory.com/581

 

서버기반 인증 


토큰기반 인증이 사용되기 전에는 Session 등을 이용한 서버기반의 인증이 대부분 사용 되었다.
Session의 경우 사용자의 인증정보를 서버 메모리에 저장하고, 사용자 인증이 많아질 수록 서버의 메모리가 부족해지는 문제가 있다.
이를 극복하기위해 서버의 메모리를 늘리기도(H/W) 하고 서로 다른 서버로 요청을 하고, 서버간의 세션동기화 작업(S/W & H/W)을 하기도한다.

 

토큰기반 인증


토큰기반은 Stateless 서버에 적합니다. 
Stateless서버란, 사용자의 요청이 이전 요청과 어떠한 관계와 종속이 되지 않는 서버를 의미합니다.

Oauth 토큰

 Random String으로 특별한 정보를 가지고 있지 않는 것이 일반적, 
서버는 이토큰을 이용하여 다시 관련된 정보를 찾아야 하므로 서버에 부담이 간다.
 API나 서비스를 제공하는 서버는 토큰을 발급받은 사용자에게 연관된 권한을 식별한뒤 토큰과 연관된 정보를 서버쪽에서 찾아서 제공해 줘야한다.

  EX)FaceBook의 String기반  AccessToken

 

OAuth 토큰 흐름

  1. 클라이언트가 토큰을 요청한다.
    이때,  토큰 발급을 요청하는 사용자의 ID/PW를 넘기고, 이와함께 권한(용도)를 요청.
  2.  서버가 계정 정보를 확인 후, 토큰 발급이 가능하면 발급, 이때 내부 저장소에 토큰에 대한 정보 저장.
  3.  토큰은 API 클라이언트로 전달
  4. 클라이언트는 이때받은 토큰으로 API 호출
  5. API 서버가 토큰을 가지고 관리자 정보 확인 후 해당 정보를 가져옴
  6. 클라이언트에게 해당 정보를 전달

 

 

Claim 토큰

 토큰을 생성 요청하는 방식은 OAuth와 동일하며, 토큰 자체에 필요한 정보들이 담겨있다. 대표적으로 JWT가 있다. 
JWT는  토큰에 필요한 정보를 JSON을 이용하여 정의한다.
{
“id”:”terry”
,”role”:[“admin”,”user”]
,”company”:”pepsi”
}

출처: https://bcho.tistory.com/999 [조대협의 블로그]


  1. 사용자를 인증 후 토큰을 생성
  2. 서버가 토큰의 정보를 저장하지 않고, 토큰에 연관되는 사용자 정보나 권한등을 토큰 자체에 넣어서 저장
  3. 클라이언트가 토큰을 가지고 API요청
  4. API서버는 토큰 내에 들어있는 사용자 정보를 가지고 권한 인가 후 결과를 리턴

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

 * SAML2.0 (XML기반)도 Claim기반의 토큰이다. Assertion의 개념으로 XML안에 정보를 넣어서 넘길 수 있으나, 사이즈가 크고 구조가 복잡하여 접근이 어렵다.
    API처럼 자주 호출해야하는 경우 HTTP헤더 등에 실어서 보내기 어렵고 오버해드가 크다. 
    SAML2.0 은 사이트나 시스템간의 SSO에서 상호 사용자 인증등을 위해서 사용된다.

 

 

JWT (Json Web Token)


JWT는 REST API호출시 JSON 형태의 데이터를  HTTP Header에 넣기 위해 BASE64 인코딩으로 변환한다.

BASE64로 인코딩된 형태
          ew0KICAiaWQiOiJ0ZXJyeSINCiAgLCJyb2xlIjpbImFkbWluIiwidXNlciJdDQogICwiY29tcGFueSI6InBlcHNpIg0KfQ0K

JWT의 장점

자가수용적 : 필요한 모든정보를 자체적으로 지니고 있기 때문에, 서버에서 클라이언트의 정보를 저장 및 관리할 필요가 없다.

안정성 : Sign 정보가 담겨있기 때문에, 보낸이가 바뀌었는지, 정보가 바뀌었는지를 검증할 수 있다.

 

변조방지

토큰을 받은 다음에 누군가 토큰을 변조해서 사용하는 것을 막기위한 무결성 보장방법으로는 서명(Signature) 이나 HMAC를 사용한다.
메세지를 변조하면, 메세지에서 생성한 해쉬값과 토큰뒤에 붙어 있는 HMAC값이 다르기 때문에 메세지가 변조되었음을 알 수 있다.
HMAC값 까지 새롭게 만들어 내려고 해도, HAMC는 앞의 비밀키를 이용하여 복호화되어 비밀키를 알 수 없는 이상 만들어낼 수 없다.

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

 

 

JWT 구조


헤더(header) . 정보(Payload) . 서명(signatrue)

 

헤더 Header 

typ (토큰타입), alt(해시 알고리즘) 이 담겨있다.  
“typ” : “JWT” , “alg” : “HS256”

 

정보 Payload

key , value 쌍으로 된 정보를 Claim이라고 한다. 등록된 클레임(registerd) , 공개 클레임 (public) , 비공개 클레임 (private) 3가지 분류가있다.

 – 등록된 클레임 (registerd)
 App 서비스에 필요한 정보가아닌, 토큰의 정보를 표현하기 위함. Optional(선택적) 이다.
iss : 토큰발급자 / sub : 토큰제목 / aud : 토큰 대상자 / exp: 토큰 만료시간 (옵션이지만 거의 필요함) / iat : 토큰 발급 시간 / jti : JWT 고유 식별자

 – 공개 클레임 (public)
  토큰에서 사용하기 위해서 정의했지만, 충돌을 방지하기 위해서 공개된 이름이다.

 – 비공개 클레임 (private)
   서비스에 필요한 정보들이 포함됨, 서버와 사용자간의 협의하에 작성된다.

 

서명 Signature

Token의 무결성을 보장하기 위해 사용. HMAC방법 이용하여 Header와 claim을 인코딩한것을 다시 비밀키를 이용하여 해싱한다.
비밀키를 알지 않는 이상 새로운 HMAC를 만들 수 없으며, 복호화가 불가능하다.

 

 

 

JWT 만료시간


토큰 내에 모든 정보가  담겨있으므로, 한번 발급된 토큰은 변경 또는 삭제가 불가능하다. 
따라서, 서명만 맞다면 사용 가능한 토큰으로 인식 하기 때문에, Expire time을 명시하고, refresh token 등을 통해 중간중간 토큰을 재발행 해야한다.

댓글 남기기