Token based authentication & JWT
Token based authentication & JWT
Token 기반 인증 방식
- 클라이언트가 서버에 접속하면, 서버가 클라이언트에게
서명된 토큰
을 발급해 주는 방식 - 클라이언트는 토큰을 쿠키 혹은 로컬 스토리지등에 저장하고, 이후 서버에 요청할 때마다 토큰을 함께 전송
- 서버는 토큰을 검증하고 요청에 응답
- Session과 달리 서버에 정보를 저장하는 것이 아니라 토큰에 정보를 저장함
Token 사용의 장점
- 세션과 비교해 추가적인 서버 저장소 관리가 필요하지 않고, 사용자 수가 많아진다고 서버 부담이 늘지 않음
- OAuth 등에서도 사용한 만큼 확장성이 높음
- 모바일 앱에서 사용이 용이
JWT
- JSON 데이터를 Base64 URL-safe 인코딩해서 직렬화한 토큰
- JSON 데이터는 Header, Payload, Signature 세 부분으로 구성됨
- 각 부분은
.
으로 구분됨
JWT의 JSON 데이터 구조
- Header
- alg와 type으로 구성됨
- alg는 서명에 적용될 해시 알고리즘을 나타냄 (SHA256, HS512 등)
- type은 이 토큰의 타입을 나타냄. JWT를 사용하므로
JWT
가 됨
- Payload
- 서버에서 첨부한 사용자 및 토큰 관련 정보를 저장하는 곳
- 하나의 key-value 형태의 데이터 조각을 claim이라고 함
- 한 토큰에 여러 claim을 넣을 수 있으며, 사용자 ID, 유효기간, JWT 발급자 등의 정보가 해당됨
- 중요한 정보를 담으면 안됨
- Signature
- 올바른 token인지 확인하기 위한 값. 다음과 같이 생성됨
- Header, Payload를
.
으로 결합해 인코딩 함 - 이후 header에 명시된 해시함수와 개인 키를 이용하고 다시 인코딩해서 signature를 얻음
JWT 단점
- 길이
- Claim에 넣는 데이터가 많아질 수록 JWT 토큰은 길어짐
- 긴 token을 전송하면 이에 따른 네트워크 비용 증가
- 토큰에 대한 수정 불가
- 한 번 발급된 토큰에 대한 수정 불가
- 만약 JWT가 탈취당하더라도 서버에서 해당 토큰에 대해 영향을 줄 수 없음
- Payload 정보가 제한적
- 디코딩이 쉽기 때문에 중요한 정보는 payload에 담을 수 없음
- 여러 보안 취약점
- Header의 alg 부분을 none으로 작성한 JWT를 통해 일부 서버를 공격 가능
- 서버에서 짧거나 일반적인 secret key를 이용하면 공격당할 수 있음
Access / Refresh Token
- 서버에 접속하기 위한 JWT를 access token이라고 함. 이 토큰은 탈취당했을 때 굉장히 위험
- 따라서 access token의 만료 기간을 짧게 설정하고, 자주 재발급 받는 것이 좋음
- 이렇게 access token을 재발급 받게 해 주는 또 다른 token(JWT)을 refresh token이라고 함
- Refresh token은 세션과 같이 서버 DB에도 정보가 저장되고, 탈취 당했을 때 서버 DB에서 삭제하면 됨
- 보안성이 증가되지만, 그 만큼 자원 사용 증가 및 구현 난이도 상승
JWT 저장 위치
Web storage
- 브라우저 내에 Local storage와 Session storage라는 저장소가 있음
- 여기에 JWT를 저장하면 서버가 HTTP를 이용해 접근이 불가능
- 그러나 자바스크립트로 접근이 가능하기 때문에 XSS 등의 공격에 매우 취약해서 사실상 token을 저장하기는 어려움
쿠키
- Web storage와 달리 쿠키에 저장하면 서버에서 접근이 가능
- HttpOnly 설정을 통해 자바스크립트의 접근을 막을 수 있음 (XSS 차단, 탈취 가능성 감소)
- Secure 옵션을 통해 HTTPS로만 전송되게 해 보안 수준을 높일 수 있음
- CSRF 공격에 위험성이 생기나, 서버에서 CORS 설정을 통해 어느 정도는 방지 가능
- Refresh token을 저장하기에 좋음
자바스크립트 로컬 변수
- 자바스크립트의 로컬 변수에 저장해 두고, http 요청에 bearer 토큰으로 담아서 전송하는 방법
- 외부에서 삽입한 자바스크립트는 로컬 변수를 사용 불가능하기 때문에 XSS에 방어가 됨
- 물론 네트워크를 통해 전송되므로, 이 과정에서 노출될 수 있음
- 따라서 만료 기간이 짧은 access token을 저장하기에 좋음
References
- https://tofusand-dev.tistory.com/89#token-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D
- https://velog.io/@ppyooy336/JWT-Token-%EC%A0%80%EC%9E%A5-%EC%9C%84%EC%B9%98
- https://velog.io/@bey1548/JWTJson-Web-Token
- https://debugdaldal.tistory.com/179
- https://tansfil.tistory.com/59
- https://youtu.be/XXseiON9CV0
- https://velopert.com/2350
- https://pronist.dev/143
- https://simsimjae.tistory.com/482
기타
2022-01-05 ~ 2022-01-07을 정리하고 합침.