JWT 토큰
목차
- JWT 토큰
- JWT 토큰의 저장방법과 사용법
- JWT 토큰을 쿠키에 저장했을 때 취약점
- 토큰 기반 인증방식
1. JWT 토큰
1. Token 인증
: 토큰 기반 인증 시스템은 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 ‘토큰’을 부여
토큰은 세션과는 달리 서버가 아닌 클라이언트에 저장되기 때문에 메모리나 스토리지 등을 통해 세션을 관리했던 서버의 부담을 덜 수 있음(클라이언트에서 받아 위조되었는지 판별만 해줌)
단점
- 쿠키/세션과 다르게 토큰 자체의 데이터 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해질수 있음
- Payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보는 담을 수 없음
- 토큰을 탈취당하면 대처하기 어려움(사용 기한을 제한하는 설정 필요)
2. JWT(JSON Web Token)
: 인증에 필요한 정보들을 암호화시킨 JSON 토큰
- JSON 데이터를 Base64 URL-safe Encode 를 통해 인코딩하여 직렬화한 것
- 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명이 들어있음
- JWT 기반 인증 : JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식 → 사용자가 JWT 를 서버로 전송하면 서버는 서명을 검증하는 과정을 거치게 되며 검증이 완료되면 요청한 응답을 돌려줌
- JWT 구조
- Header(헤더) : JWT 에서 사용할 타입과 해시 알고리즘의 종류
- Payload(내용) : 서버에서 첨부한 사용자 권한 정보와 데이터(실제 JWT 를 통해서 알 수 있는 데이터로 사용될 정보에 대한 내용)
- Signature(서명) : Header 에 명시된 해시함수를 적용하고, 개인키(Private Key)로 서명한 전자서명이 담겨있음(토큰의 위변조 여부를 확인하는데 사용)
- JWT의 장점
- Header와 Payload를 가지고 Signature를 생성하므로 데이터 위변조를 막을 수 있음
- 별도의 저장소가 필요없음
- 다른 로그인 시스템에 접근 및 권한 공유가 가능 (쿠키와 차이)
- 모바일 어플리케이션 환경에서도 잘 동작(모바일은 세션사용 불가)
- JWT의 단점
- 토큰 자체에 정보를 담고 있으므로 양날의 검
- 토큰의 Payload에 3종류의 클레임을 저장하기 때문에, 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있음
- BASE64로 인코딩 된 것이기 때문에, 중간에 Payload를 탈취하여 디코딩하면 데이터를 볼 수 있으므로, payload에 중요 데이터를 넣지 않아야 함
2. JWT 토큰의 저장방법과 사용법
이미지 출처 : https://velog.io/@hoo00nn/Token-%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D%EC%9D%B4%EB%9E%80
- 사용자가 ID, PW를 입력하여 서버에 로그인 인증을 요청한다.
- 서버에서 클라이언트로부터 인증 요청을 받으면, Header, PayLoad, Signature를 정의한다.
Hedaer, PayLoad, Signature를 각각 Base64로 한 번 더 암호화하여 JWT를 생성하고 이를 쿠키에 담아 클라이언트에게 발급한다. - 클라이언트는 서버로부터 받은 JWT를 로컬 스토리지에 저장한다. (쿠키나 다른 곳에 저장할 수도 있음)
API를 서버에 요청할때 Authorization header에 Access Token을 담아서 보낸다. - 서버가 할 일은 클라이언트가 Header에 담아서 보낸 JWT가 내 서버에서 발행한 토큰인지 일치 여부를 확인하여 일치한다면 인증을 통과시켜주고 아니라면 통과시키지 않으면 된다.
인증이 통과되었으므로 페이로드에 들어있는 유저의 정보들을 select해서 클라이언트에 돌려준다. - 클라이언트가 서버에 요청을 했는데, 만일 액세스 토큰의 시간이 만료되면 클라이언트는 리프래시 토큰을 이용해서
- 서버로부터 새로운 엑세스 토큰을 발급 받는다.
이중으로 나누어 인증(토큰 탈취 위험성으로 인해)
- Acess Token과 Refresh Token은 둘다 똑같은 JWT
- 토큰이 어디에 저장되고 관리되는지에 따른 사용 차이
Access Token(접근) : 클라이언트가 갖고있는 실제로 유저의 정보가 담긴 토큰
클라이언트에서 요청이 오면 서버에서 해당 토큰에 있는 정보를 활용하여 사용자 정보에 맞게 응답을 진행Refresh Token(재발급) : 새로운 Access Token을 발급해주기 위해 사용하는 토큰
보통 데이터베이스에 유저 정보와 같이 기록
3. JWT 토큰을 쿠키에 저장했을 때 취약점
- LocalStorage에 저장
- XSS 공격에 취약(JS를 통해 LocalStorage에 접근할 수 있기때문)
- CSRF공격에는 방어
- Cookie에 저장
- XSS에 탈취당할 가능성 O but, HttpOnly의 옵션으로 Script가 Cookie를 읽어올 수 없게 함 → XSS 방어 가능
- CSRF공격에는 취약 but, JWT Token을 Cookie가 아닌 Header에 넣고 요청을 보내면 방어 가능 → but, 이 경우 HttpOnly 옵션을 해제해야함
- CSRF 방어하기
- CSRF Token : 임의의 난수(CSRF Token)를 생성해 서버 메모리(세션)에 저장하고 클라이언트에 전달
- Cookie Referer Check : 허용한 Domain에서 온 요청인지 체크
- Cookie SameSite : 외부 사이트에 쿠키 전송할 범위를 설정 가능
→ cookie > localStorage
* XSS(Cross Site Scripting) : 보안이 취약한 웹사이트에 악의적인 스크립트를 넣어놓고 사용자가 이 스크립트를 읽게끔 유도하여 유저의 정보를 빼오는 공격 기법
보통 웹사이트 게시글에 악의적인 스크립트를 넣어 유저가 게시글에 들어가게끔 유도하게 하여 공격
* CSRF(Cross-site request forgery) : 사용자 의지와는 상관없이 해커가 의도한 행위(수정, 삭제, 등록 등)를 사용자 권한을 이용해 서버에 요청을 보내는 공격
4. 토큰 기반 인증방식
이미지 출처 : https://velopert.com/2350
- 사용자가 아이디와 비밀번호로 로그인을 한다.
- 서버 측에서 사용자(클라이언트)에게 유일한 토큰을 발급한다.
- 클라이언트는 서버 측에서 전달받은 토큰을 쿠키나 스토리지에 저장해 두고, 서버에 요청을 할 때마다 해당 토큰을 HTTP 요청 헤더에 포함시켜 전달한다.
- 서버는 전달받은 토큰을 검증하고 요청에 응답한다.
- 토큰에는 요청한 사람의 정보가 담겨있기에 서버는 DB를 조회하지 않고 누가 요청하는지 알 수 있다.
출처