jwt에 대해 알아보자
jwt를 제대로 알아보기전에 비슷한 인증방식인 쿠키, 세션에 대해 먼저 알아보자
쿠키란?
클라이언트가 웹사이트를 방문할 때 그 사이트가 사용하고 있는 서버를 통해 클라이언트 브라우저에 설치되는 작은 기록 정보 파일
1. 브라우저가 서버에 요청을 보낸다.
2. 서버는 클라이언트 요청에 대해 응답으로 클라이언트 측에 저장하고 싶은 정보를 응답 헤더의 Set-Cookie를 하여 보낸다.
3. 이후 클라이언트는 요청을 보낼 때마다 클라이언트에 저장된 쿠키를 요청 헤더의 담아 보낸다.
쿠기 단점
1. 보안에 취약하다. 클라이언트가 서버로 보낼 때 그대로 값을 보내기 때문에
2. 사이즈가 커질수록 네트워크 부하가 심해진다.
세션인증
이러한 쿠키의 보안적인 이슈를 해결하기 위해 민간한 정보들을 서버측에 저장하고 관리한다.
1. 클라이언트가 페이지에 요청한다.
2. 서버는 접근한 클라이언트의 Request-Header 필드인 Cookie를 확인하여, 클라이언트가 해당 session-id를 보냈는지 확인한다.
3. session-id가 존재하지 않는다면 서버는 session-id를 생성해 클라이언트에게 넘겨준다.
4. 클라이언트는 서버로부터 받은 session-id를 쿠키에 저장한다.
5. 클라이언트는 서버에 요청시 이 쿠키의 session-id 값을 같이 서버에 전달한다.
6. 서버는 전달받은 session-id로 session에 있는 클라이언트 정보를 가지고 요청을 처리 후 응답한다.
세션 단점
서버에서 세션 저장소를 사용하므로 요청을 많아지면 서버에 부하가 심해진다.
token 인증
토큰 기반 인증 시스템은 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 '토큰'을 부여한다.
토큰은 세션과는 달리 서버가 아닌 클라이언트에 저장되기 때문에 메모리나 스토리지 등을 통해 세션을 관리했던 서버의 부담을 덜 수 있다.
JWT(JSON Web Token)란?
인증에 필요한 정보들을 암호화시킨 JSON토큰을 의미한다. 일반적으로 클라이언트와 서버 사이에서 통신할 때 권한을 위해 사용하는 토큰이다.
JWT구조
JWT는 .을 구분자로 나누어진다.
header, payload, signature 이렇게 세 파트로 나누어져 있다.
header
header에는 어떠한 알고리즘으로 암호화 할 것인지, 어떠한 토큰을 사용할지에 대한 정보가 들어있다.
payload
전달하려는 정보가 들어있다. 노출과 수정이 가능한 지점이기 때문에 최소한의 정보(아이디,비밀번호 등 개인정보가 아닌)
만을 담아야한다.
signature
header와 payload를 Base64 URL-safe Encode하여 토큰을 변조하기 어렵게 만든다.
예를 들어 누군가가 Payload내용을 수정하였지만 signature에는 조작되기전에 정보가 들어가있기 때문에 악용이 어려워진다.
JWT의 동작원리
- 사용자가 id와 password를 입력하여 로그인 요청을 한다.
- 서버는 회원DB에 들어가 있는 사용자인지 확인을 한다.
- 확인이 되면 서버는 로그인 요청 확인 후, secret key를 통해 토큰을 발급한다.
- 이것을 클라이언트에 전달한다.
- 서비스 요청과 권한을 확인하기 위해서 헤더에 데이터(JWT) 요청을 한다.
- 데이터를 확인하고 JWT에서 사용자 정보를 확인한다.
- 클라이언트 요청에 대한 응답과 요청한 데이터를 전달해준다.
IF
- 클라이언트가 서버에 요청을 했는데, 만일 액세스 토큰의 시간이 만료되면 클라이언트는 리프래시 토큰을 이용해서
- 서버로부터 새로운 엑세스 토큰을 발급 받는다.
JWT장점
1. Signature로 데이터 위변조를 막을 수 있다.
2. 인증 정보에 대한 별도의 저장소가 필요없다.
3. 서버는 무상태가 되어 서버 확장성이 우수해질 수 있다.
JWT단점
1. 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.
2. stateless특징을 가지기 때문에 토큰을 클라이언트 측에서 관리한다. 이말은 토큰 자체를 탈취당하게 되면 대처가 어렵게 된다.
그래서 2번의 해결법은?
access refresh token
Access Token이 탈취되면 토큰이 만료되기 전까지 누구나 권한 접근이 가능해진다. 그래서 유효시간을 부여하는 식으로 탈취문제에 대응을 해야한다. 다만 유효기간이 짧으면 사용자는 로그인을 자주해야하는 불편함이 있다. 그렇다고 유효기간을 늘리자니 토큰을 탈취당했을 때의 위험도가 높아진다. 어떻게 해야할까??
바로 Refresh Token을 사용하는 것이다
재발급에 관여하는 토큰이다.
1. 사용자가 ID , PW를 통해 로그인.
2. 서버에서는 회원 DB에서 값을 비교
3~4. 로그인이 완료되면 Access Token, Refresh Token을 발급한다. 이때 회원DB에도 Refresh Token을 저장해둔다.
5. 사용자는 Refresh Token은 안전한 저장소에 저장 후, Access Token을 헤더에 실어 요청을 보낸다.
6~7. Access Token을 검증하여 이에 맞는 데이터를 보낸다.
8. 시간이 지나 Access Token이 만료됐다.
9. 사용자는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보낸다.
10~11. 서버는 Access Token이 만료됨을 확인하고 권한없음을 신호로 보낸다.
Tip
Access Token 만료가 될 때마다 계속 과정 9~11을 거칠 필요는 없다.
사용자(프론트엔드)에서 Access Token의 Payload를 통해 유효기간을 알 수 있다.
따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료됐다면 곧바로 재발급 요청을 할 수도 있다.
12. 사용자는 Refresh Token과 Access Token을 함께 서버로 보낸다.
13. 서버는 받은 Access Token이 조작되지 않았는지 확인한후, Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교한다. Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 발급해준다.
14. 서버는 새로운 Access Token을 헤더에 실어 다시 API 요청 응답을 진행한다.
재발급 여부는 여러 case가 있다.
case1 : access token과 refresh token 모두가 만료된 경우 → 에러 발생 (재 로그인하여 둘다 새로 발급)
case2 : access token은 만료됐지만, refresh token은 유효한 경우 → refresh token을 검증하여 access token 재발급
case3 : access token은 유효하지만, refresh token은 만료된 경우 → access token을 검증하여 refresh token 재발급
case4 : access token과 refresh token 모두가 유효한 경우 → 정상 처리
보통 Access Token 만료시간은 30분 Refresh Token은 2시간이다.
궁금한 질문
jwt는 stateless방식인데 refresh토큰을 db에 저장하는건 statefull방식이 아닌가?
궁금한점
access토큰이 탈취당했을 시의 위험성을 대비하기 위해 refresh token을 사용하는데 refresh token이 탈취당한다면 똑같은 결과가 나오는 것이 아닌가? 오히려 유효기간이 더 길어서 더 위험한 것이 아닌가?
'백엔드 > 뎁스스터디' 카테고리의 다른 글
5- 동시성 처리 (2) (1) | 2024.05.28 |
---|---|
5- 동시성 처리 (1) (0) | 2024.05.20 |
3- 스프링 시큐리티 + jwt (1) (0) | 2024.05.07 |
2- TDD(2) (1) | 2024.04.07 |
1- TDD(1) (0) | 2024.04.02 |