인프런 강의 를 참고하여 정리한 글 입니다.
📚 1. JWT(JSON Web Token)란 무엇인가?
✔️ JWT란 무엇인가?
- JWT는 RFC 7519 웹 표준으로 지정 되어있다.
- JSON 객체를 사용해서 토큰 자체에 정보들을 저장하고 있는 Web Token이라고 정의할 수 있다.
- 간편하게 사용 가능하다!
📖 A. JWT의 구성
- JWT는 Header, Payload, Signature 3개의 부분으로 구성되어 있다.
✔️ Header
- 헤더는 Signature를 해싱하기 위한 알고리즘 정보들이 담겨져있다.
- 즉, JWT를 어떻게 검증(Verify)하는 가에 대한 내용이 담겨있다.
- 일반적으로 서명 알고리즘과 타입의 두 부분으로 구성된다.
alg
: 서명시 사용하는 알고리즘
kid
: 서명시 사용하는 키(Public/Private)를 식별하는 값
✔️ Payload
- 서버와 클라이언트가 주고받는, 시스템에서 실제로 사용될 정보에 대한 내용을 가지고 있다.
- Payload에 있는 각각의 속성은
Claim
이라 하고, 속성들을 Claim Set
이라고 한다.
✔️ Signature
- 점(.)을 구분자로 Header와 Payload를 합친 문자열을 서명한 값
- Signature는 Header의 alg에 정의된 알고리즘과 비밀 키를 이용해 생성한다.
- 토큰의 유효성 검증을 위한 문자열
- 이 문자열을 통해 서버는 이 토큰이 유효한 토큰인지를 검증할 수 있다.
📖 B. JWT 특징
Header와 Payload 모두 Base64(URF-Safe)로 인코딩 되어 있다.
Decode하면 내용을 읽어낼 수 있다.
Header에는 알고리즘과 타입, Payload는 데이터를 담고 Signature를 이용하여 검증한다.
Payload에 노출될 수 있는 정보를 담아서는 안된다.
✔️ JWT 장점
- 중앙 인증 서버
- 데이터 스토어에 대한 의존성 없음
- 시스템의 수평 확장 유리
- Base64 URL Safe Encoding을 사용하기 때문에 URL, Cookie, Header 모두 사용 가능
✔️ JWT 단점
- Payload의 정보가 많아지면 네트워크 사용량(traffic) 증가하기 때문에 설계 시 주의가 필요
- 토큰이 클라이언트에 저장되므로 서버에서 클라이언트의 토큰을 조작할 수 없다.
📚 2. JWT 사용법
📖 A. 왜 JWT를 사용하는 걸까?
✔️ Self-Contained한 속성을 가지고 있다.
- JWT가 스스로 인증에 필요한 데이터를 가지고 있다. ( ex. userid )
✔️ Stateless하다.
- 세션과는 달리 백엔드 서버가 바뀌어도 인증이 가능하다.
- 비밀번호를 다시 입력할 필요가 없다.
- Scale Out 하더라도 대응이 가능하다.
- Validation Check만으로 검증이 가능하다.
(그럼에도 white list 방식의 추가 검증을 하는 경우도 있다.)
✔️ 모바일 환경에서 다시 로그인 할 필요가 없다.
- 백그라운드로 돌릴 수 있는 앱이 한정되어 있다. ( = 세션이 날아간다. )
📖 B. JWT는 어떻게 스스로 검증할 수 있을까?
- Signature 영역은 Header와 Payload의 문자열, SecretKey를 더해 암호화 한다고 하였다.
- 이 때 만약 사용자 A가 토큰을 조작한 후,
Payload의 A의 ID를 B의 ID로 바꾸고 토큰을 서버로 보낸다고 가정한다.
- 서버는 토큰을 받아 SIgnature를 검증한다.
- 이 때 Payload는 B의 ID가 들어있지만, Signature는 기존의 Payload(A의 ID)를 통해 만들어져있기 때문에 유효하지 않은 토큰으로 간주한다.
📖 C. Jwt는 어떻게 사용할까?
- 사용자가 로그인한다.
- 서버에서 계정정보를 읽어 사용자를 확인하여
사용자의 고유한 ID 값을 부여한 뒤 기타 정보와 함께 Payload에 넣는다.
- JWT 토큰의 유효기간을 설정한다.
- 암호화할 Secret Key를 이용해 Access token을 발급한다.
- 사용자는 Access token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보낸다.
Authorization: Bearer <token>
- 요청을 보낼 때 JWT 토큰을 Authorization header 필드에 담아보낸다.
- 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후,
조작여부/유효기간을 확인한다.
- 검증이 완료되면 Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져온다.
📖 D. Access Token & Refresh Token
- Access Token은 짧은 생명 주기를, Refresh Token은 보다 긴 생명 주기를 갖는다. ( 구체적인 기간은 케이스마다 다르다. )
- 서버로 요청 시 Access Token을 사용하고 Access Token이 만료되면,
Refresh Token을 이용해서 새로운 Access Token을 받아온다.
- Refresh Token도 만료된다면 다시 로그인을 해야한다.
- Access Token이 탈취당하는 경우, 공격자는 사용자와 동일한 권한을 갖게 된다.
=> JWT를 사용하는 경우 반드시 SSL을 이용한 암호화 통신을 사용해야 한다.
- 보안이 중요한 서비스의 경우 JWT가 Stateless함에도 불구하고,
Redis등에 발급한 Access Token을 보관하기도 한다.(로그아웃 시 Redis에서 삭제)
위에 kid는 header에 들어있는건가요? ㅠㅠ