팀 프로젝트에서 사용했던 JWT에 대해 더 알아보기
개념
- Json Web Token
- 웹에서 사용되는 JSON 형식의 토큰
- 사용자 '인증 수단'으로 주로 쓰임
- 토큰을 통해 인증이 포함된 요청이 유효한지 확인
JSON
key, value가 한 쌍을 이루는 객체
사용법
- 클라이언트에서
Authorization
헤더에 Bearer ${토큰}
형태로 설정하여 서버로 전송
- 토큰에 포함되어 있는 서명(signature) 정보를 통해 서버에서 유효성 여부를 검증
- JWT 토큰은 Base64로 인코딩이 되어 있고 'eyJ' 문자로 시작하는 아주 긴 문자열
- 온라인 디버거를 통해서 저장되어 있는 내용을 쉽게 JSON 형태로 디코딩해서 확인 가능
(= 보안은 . . .)
구조
- 헤더(header): 해시 알고리즘(alg)과 토큰 타입(typ) 설정
"alg": "HS256"
은 HMAC SHA 256 (해시 알고리즘 중 한 가지)
"typ": "JWT"
는 '이 토큰을 JWT로 지정한다'는 뜻
- 내용(payload): 실제로 전달되는 데이터
- 데이터 각각의 키 = claim (-> 사용자가 원하는 key와 value로 구성)
- 서명(signature): 헤더와 내용을 '비밀키(secret)'로 서명하여 저장
JWT에서 자주 사용되는 키 이름
- sub: 인증 주체(subject)
- iss: 토큰 발급처(issue)
- typ: 토큰 유형(type)
- alg: 해시 알고리즘(algorithm)
- iat: 발급 시각(issued at)
- exp: 만료 시점(expiration time)
- aud: 클라이언트(audience)
사용 예시
- 클라이언트가 서비스의 인가 서버를 통해 로그인에 성공하면 JWT 토큰을 획득
- 이후 클라이언트가 해당 서비스의 API를 호출할 때 JWT 토큰을 보내서 원하는 자원에 접근하거나 허용된 작업 수행
장점
- JWT가 등장하기 전: 쿠키(cookie)와 세션(session)을 통해 사용자 인증을 구현
- JWT는 토큰 자체에 사용자의 정보가 저장되어 서버 입장에서 토큰을 검증만 해주면 됨
- 반면에 쿠키와 세션은 로그인한 모든 사용자의 세션을 서버의 DB나 캐시에 저장해놓고 쿠키에서 넘어온 세션 아이디로 사용자를 조회
- JWT를 사용하면
- 사용자 수가 늘어나더라도 사용자 인증을 위해서 서버에 추가로 투자해야 하는 비용이 절감되어 서버 확장성이 높아짐
- 쿠키를 사용하지 않아서 CORS 문제에서 자유로움
한계
- 어느 정도 규모 있는 서비스에서는 사용자 인증 용도로 JWT를 사용하기 어려움
- 예) 현재 로그인된 사용자가 쓰는 여러 기기 중 특정 기기에서 로그아웃을 시키려면 JWT 대신 서버에 사용자 세션을 저장해야 함
유의 사항
- JWT 토큰의 payload는 단순히 Base64로 인코딩된 파트이기 때문에 디코딩만 하면 누구나 열람 가능
- 민감한 사용자 정보(예: password)를 payload에 담지 않아야 함
- payload에는 사용자를 식별할 수 있는 아이디 정도만 저장
- 사용자에 대한 추가 정보가 필요한 경우 서버에서 직접 사용자 데이터가 들어있는 DB 조회
- 불가피한 이유로 JWT 토큰에 민감한 사용자 정보를 저장해야한다면 반드시 암호화를 하여 디코딩한 후에도 알아볼 수 없게 해야 함
종류: accessToken과 refreshToken
- accessToken: 서버의 API를 사용하기 위한 인증용 토큰
- 만료가 되면 토큰이 없거나 무효화된 것으로 보고 해당 사용자의 접근을 막을 수 있음
- refreshToken: accessToken의 재발급을 위한 토큰
- refreshToken도 accessToken과 마찬가지로 로그인할 때 발급 받음
- refreshToken이 유효해야 accessToken을 재발급 받을 수 있고, refreshToken으로 accessToken을 재발급 받으면 별도의 추가 로그인 필요 없이 서비스를 정상적으로 이용할 수 있음
- refreshToken마저 만료되었다면 처음부터 로그인을 다시 해야 함
- 일반적으로 accessToken보다 refreshToken의 만료 기간이 김
서버의 JWT 유효 여부 판별법
- 클라이언트에서 토큰을 서버로 보냄
- 서버는 복호화 로직을 통해 서명의 Secret을 확인 + 복호화된 토큰 데이터가 DB의 토큰 정보와 일치하는지 확인
JWT 보안
보안은 무조건 강한 게 좋은가?
- No
- 너무 과하면 서비스에 부담을 주기도 함
- JWT는 헤더, 내용, 서명 으로 구성
- 이 중에 서명을 제외한 2가지(헤더, 내용)는 디코딩을 통해 누구나 들여다 볼 수 있음
- JWT뿐만 아니라 다른 보안을 함께 사용하는 것이 좋다.
다른 보안 사용하기: Cookie에 JWT 저장
- 쿠키는 반드시 Cookie 옵션을 세팅하고 사용
- Cookie는 기본적으로 브라우저에 직접 저장되고 자동으로 제거되지 않기 때문
- 토큰에 만료 기한 설정
- 토큰의 유효 기간을 지정하여 발급
- 만료된 후에는 브라우저 쿠키에서 제거됨
- CORS(Cross-Origin Resource Sharing) 방지
- HTTP 요청/응답 도메인 제한하기
- 서비스의 도메인을 domainofeon.com이라고 가정
- 예: domainofeon.com에서만 CORS 허용
Access-Control-Allow-Origin: domainofeon.com
- 2) XSS(크로스 사이트 스크립팅) 공격 방지하려면?
참고 자료
JWT - Json Web Token
JWT란 무엇인가? 그리고 어떻게 사용하는가? (1) - 개념
JWT란 무엇인가? 그리고 어떻게 사용하는가? (2) - 사용처
JWT란 무엇인가? 그리고 어떻게 사용하는가? (3) - 보안