[WEB] JWT 토큰 인증

minidoo·2021년 1월 13일
0

WEB

목록 보기
2/8
post-thumbnail
post-custom-banner

웹 서비스를 만들 때 구현해야 하는 것 중 하나는 인증이다.
이전에는 서버에 저장하는 세션/쿠키 방식을 사용했지만, 최근에는 토큰을 이용한 인증 방식을 많이 사용한다. 토큰을 이용한 인증 방식 중 하나가 JWT(Json Web Token)이다.

JWT는 JSON 형태로 되어 있는 웹 토큰이다.
JWT는 서버에 토큰 정보를 저장하지 않는다. 서버는 해당 토큰이 유효한지만 체크한다.

토큰 인증 프로세스

  1. 클라이언트는 아이디, 암호를 입력하여 서버에 인증을 요청한다.
  2. 서버에서 인증이 완료되면 토큰을 생성하여 클라이언트에 건넨다.
  3. 클라이언트는 토큰을 받아 인증이 필요할 때마다 토큰을 함께 전달한다.
  4. 서버는 토큰을 검증하여 이에 따라 요청한 자원을 제공한다.

JWT 토큰 구성

JWT = 머리(Header) + 페이로드(Payload) + 서명(Signature)

Header

Header은 JWT를 어떻게 검증(Verify) 하는가에 대한 정보를 담고 있다.
( 서명에 사용하는 암호화 방식에 대한 정보 )

{
     "alg" : "HS256",	// 서명 시 사용하는 알고리즘
     "kid" : "key ID"	// 서명 시 사용하는 키
}

위의 JSON 객체를 문자로 직렬화하고 인코딩을 하여 헤더를 생성한다.

Base64URLSafe(UTF-8('{"alg": "ES256","kid": "Key ID"}'))

Paload

JWT의 실제 내용이 담겨진다.
각 속성들을 클라임 셋(Claim Set)이라 부르며 토큰 생성자, 생성 일시 등에 대한 값들로 구성한다.

토큰의 유효기간 검사를 위해 토큰 발생 시점에 대한 속성을 생성한다.

{
    "iss": "miniddo",
    "iat": "1586364327"
}
Base64URLSafe('{"iss": "miniddo","iat": "1586364327"}')

Signature

암호화하여 위조를 방지한다.
점(.)을 구분자로 Header와 Payload를 합친 문자열을 서명한 값이다.

key 값이 필요하다. 내용은 같지만, key 값에 따라 다른 결과가 나온다.

Base64URLSafe(Sign('ES256', '${PRIVATE_KEY}', 'Header값.Payload값')))

JWT

점(.)을 구분자로 Header, Payload, Signature을 합치면 JWT가 완성된다.

Header값.Payload값.Signature값

전체 코드

header = '{"alg":"HS256", "kid" : "key ID", "typ":"JWT"}'; 
payload = '{"iss": "miniddo", "iat": "1586364327"}'; 

// 암호화에 사용될 key 값 
key = 'antsecretkey'; 

// 암호화된 서명을 만들어 내기 위한 부분, 앞서 말한대로 header 와 payload 를 합친다. unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload); 
signature = HMAC-SHA256(key, unsignedToken); 

// 다 만들어졌으니 세 부분을 모두 합친다. 
token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature);

이렇게 만들어진 토큰은 Header의 alg, kid 속성과 공개 키를 이용해 검증한다.
서명 검증이 완료되면 JWT의 모든 내용을 신뢰하고 Payload 값으로 원하는 처리를 한다.

post-custom-banner

0개의 댓글