-
[NewWork] 토큰 기반 인증network 2024. 1. 24. 18:00728x90반응형
토큰 기반 인증
토큰을 기반으로 한 인증에 대해서 알기 전에 기존에 쓰이던 세션 기반 인증에 대해서도 같이 정리해보겠음
세션(Session)이란?
사용자가 웹 브라우저를 통해 웹 서버에 접속한 시점으로부터 웹 브라우저를 종료하여 연결을 끝내는 시점까지 같은 사용자로부터 오는 일련의 요청을 하나의 상태로 보고 그 상태를 일정하게 유지하는 기술
즉, 클라이언트 별로 각각의 상태 정보를 서버에 저장하는 기술임
- 서버에서 클라이언트를 구분하기 위해 각 클라이언트 별로 세션ID를 부여하고, 웹 브라우저가 서버에 접속해 브라우저를 종료할 때까지 세션을 유지함
- 접속 시간에 제한을 두어 일정 시간 응답이 없다면 정보가 유지되지 않게 설정가능
- 사용자가 많아질 수록 서버 메모리를 많이 차지하게 됨 -> 서버에 부하가 생길 수 있음
- 쿠키에 비해 보안적인 면에서 좀더 나음(쿠키는 중간에 정보를 탈취할 수 있으므로)
- 브라우저 종료 시 만료기한에 상관없이 종료됨
세션 기반 인증 방식
세션 기반 인증
- 사용자가 서버에 authentication 요청을 보냄(닉네임, 패스워드 같은 유저정보를 같이 보냄)
- 서버는 서버에 저장된 회원 데이터와 비교해 일치하면 사용자가 맞다는 인증을 하고 세션을 만들어 세션 아이디를 HTTP 응답 헤더에 Set-Cookie안에 세션아이디를 넣어 클라이언트에게 보냄
- 클라이언트는 응답을 받아 set-cookie를 보고 자동으로 브라우저 쿠키에 세션아이디를 저장하고 매번 서버에게 요청을 보낼 때 HTTP 헤더에 세션아이디가 담긴 쿠키를 같이 보냄 → 서버가 매번 세션 아이디를 확인하고 서버에 저장된 세션아이디와 일치하면 사용자가 요청한 응답을 클라이언트로 보냄
세션 기반 인증 문제점
세션 기반 인증에서는 서버에서 세션을 생성하고, 세션 정보를 서버에 저장함. 서버는 세션 아이디를 통해서 해당 사용자의 상태 정보(로그인 상태 등)을 조회함
하지만 이 방식은 서버에서 세션을 관리하기 때문에 유저에 대한 세션 아이디를 메모리에 저장함. 유저수가 늘어나면 세션이 늘어나므로 자연스럽게 메모리 사용량이 증가함 → 만약 동시 접속하는 유저의 수가 많다면 서버 메모리의 공간이 부족해 서버에 부하가 걸리거나 화면이 움직이지 않는 문제가 발생할 수도 있음
또한 브라우저의 쿠키에 저장된 세션아이디가 탈취당하거나 조작될 수 있음
→ 어떻게? → 제 3자나 해커가 쿠키값을 볼 수 있는 코드를 몰래 심어서 세션아이디 값을 알 수 있음(xss(Cross-Site Scripting 예시 페이지))
토큰(Token)이란?
토큰은 인증이 필요한 시스템에서 사용자의 인증 정보를 암호화하여 생성한 문자열을 말함
사용자가 시스템에 로그인하면 해당 사용자의 식별 정보를 바탕으로 토큰이 생성되며, 이는 사용자가 서버에 요청을 보낼 때마다 함께 전송되어 사용자의 신원을 확인하는데 사용됨
토큰 기반 인증 방식은 사용자의 상태를 저장하지 않으므로 Stateless한 특성을 가져 세션 기반 인증 방식에 비해 서버의 부하를 줄이고 확장성이 있음토큰 기반 인증 방식
토큰 기반 인증 방식
- 사용자가 서버에 authentication 요청을 보냄
- 사용자가 보낸 데이터가 맞는지 유효성 검사를 하고, 유효성 검사를 통과하면 유니크한 값을 가진 토큰을 생성해 클라이언트로 보냄
- 서버에서 받은 토큰을 클라이언트에 저장하고(쿠키 등), 서버에 요청을 할 때마다 HTTP 헤더에 토큰을 같이 보냄
- 서버는 클라이언트로 부터 받은 토큰을 검증하고 유효한 토큰일 경우 클라이언트에서 요청한 응답을 보냄
토큰 기반 인증 문제점
토큰도 중간에 탈취당할 수 있음(xss, man-in-the-middle-attack 등) → 탈취당한 토큰을 무효화할 수 없음(왜냐하면 토큰을 서버에서 관리하는 게 아니기 때문에 제 3자가 탈취한 토큰은 만료기한이 될 때까지 무표화할 수 없음)
JWT(JSON Web Token)
토큰의 한 종류로, 인증에 필요한 정보들을 암호화시킨 JSON 토큰을 의미함.
구성 요소
- Header
{
"alg": "HS256",
"typ": "JWT"
}토큰의 종류와 서명 알고리즘에 대한 내용이 담겨있음
- Payload
payload는 토큰에서 사용할 정보의 조각들(
클레임
)이 담겨있음클레임이란?
key-value 형식으로 이루어진 한 쌍의 정보(내용)를 의미함
서버와 클라이언트가 주고 받는 시스템에서 실제로 사용될 정보에 관한 내용을 담고 있음payload는 크게 세 가지로 나눌 수 있음
1. registered claims(등록된 클레임)미리 정해져있는 클레임으로 서비스에서 필요한 정보가 아닌 토큰에 대한 정보를 담기 위해 이름이 이미 정해진 클레임을 말함. 필수 클레임은 없지만 많이 쓰이는
사실상의 표준
이 있음- 종류
- iss(issuer: 토큰 발행자)
- sub(subject: 토큰 제목)(제일 중요함)
- iat(issued at: 토큰 발행 시간)
- public claims(공개 클레임)
사용자가 정의할 수 있는 클레임.
공개할 수 있는 정보를 전달하기 위해 사용하며 충돌이 방지된 이름을 가지고 있어야 함. 이를 위해서 uri 형식으로 클레임 이름을 지음
ex: { “https:// www.example.com/admin” : true }
- private claims(비공개 클레임)
클라이언트와 서버 간 협의하에 사용되는 클레임임.
ex: { username : ‘gg’ }
- Signature
서버는 헤더 혹은 페이로드가 누군가에 의해 변조되었는지 그 무결성을 검증하고 보장할 수 있음
JWT의 검증 및 생성과정
- JWT 생성: 서버에서 사용자 인증 -> 헤더와 페이로드를 각각 Base64Url 인코딩하여 문자열을 만듦 -> 두 문자열을 붙여 서버에 저장된 시크릿키(서버에만 저장되어있음. 클라이언트에서는 알 수 없음)를 사용해 헤더에 명시된 알고리즘으로 해시를 생성-> 생성한 해시값을 다시 Base64Url 인코딩 -> JWT의 서명 부분 만듦 -> 생성된 JWT를 클라이언트에게 전달
- JWT 검증: 클라이언트가 서버에 요청을 보낼 때 JWT를 함께 보냄 -> 서버는 받은 JWT의 헤더와 페이로드를 분리해 Base64Url 디코딩 -> 디코딩한 헤더와 페이로드를 붙인 문자열 + 서버에 저장된 비밀 키를 사용해서 해시를 생성 -> 이 해시값과 JWT의 서명(signature) 부분 비교 -> 만약 두 값이 일치하면 토큰이 변조되지 않았다는 것을 의미함
Access, Refresh Token
JWT을 사용해 로그인을 할 때, 유효기간이 짧은 토큰을 발급하게되면 사용자 입장에서 자주 로그인을 해야하기 때문에 번거로움
반대로 유효기간이 긴 토큰을 발급하게되면 제 3자에게 토큰을 탈취당할 경우 보안에 취약함
만약 JWT가 탈취 당했다면 서버에서는 해당 토큰이 만료될 때까지 할 수 있는 것이 없음(이미 발행된 토큰에 대해서는 서버에서 제어를 할 수 없음)이런 취약점을 막고자 Access Token과 Refresh Token을 함께 사용하는 방법을 많이 사용함
예를 들면 유저가 로그인을 하면 서버에서 엑세스 토큰과 리프레쉬 토큰을 같이 발급해서 줌
사용자가 서비스를 이용하다가 엑세스 토큰의 만료기한이 지나면 처음에 같이 발급되었던 리프레쉬 토큰(엑세스 토큰보다 만료기한이 긺. 보통 2주라고 함)을 통해 서버에 엑세스 토큰의 재발급을 요청함하지만 리프레쉬 토큰까지 탈취된다면 공격자는 엑세스 토큰을 발급받아 원래 사용자 인것처럼 행세를 할 수 있음 -> 이에 대한 조치도 추가로 필요(ex: 리프레시 토큰이 사용될 때마다 새 리프레시 토큰을 발급하여 이전의 리프레시 토큰을 무효하는 등)
JWT 토큰을 쿠키에 저장했을 때 취약점
크로스 사이트 요청 위조(CSRF) 공격
사용자가 의도치 않게 공격자가 의도하는 행동을 하게 만들어서 특정 웹사이트에 요청하게 만드는 공격임
예를 들어 은행에 로그인함(세션 아이디 있음) → 누군가 카톡이나 문자 메세지 등으로 동영상 링크(예를 들면 1분만에 휴대폰 빠르게 만들기라는 유튜브 영상 링크)를 보냄 → 클릭함 → 정상적으로 유튜브 동영상이 나옴 → 하지만 소스보기로 확인해보면 그 링크 속에 12345라는 계좌로 100만원을 입금하라는 요청을 하는 링크가 숨겨져있음 → 사용자도 모르게 12345라는 계좌로 100만원을 보내는 요청을 하고, 쿠키에 있는 세션아이디가 자동으로 요청과 함께 보내짐
크로스 사이트 스크립팅(XSS) 공격
공격자가 웹사이트에 악성 스크립트를 삽입하는 공격자세한 예시는 여기를 참조
그럼 어디다가 저장하는 게 좋을까?
아래의 블로그를 참조반응형'network' 카테고리의 다른 글
[NetWork] OAuth와 JWT의 차이점 (0) 2024.01.30 [NetWork] REST API (1) 2024.01.29 [NetWork] cookie, session, web storage (1) 2024.01.23 [NetWork] 브라우저에 www.naver.com을 입력하면 일어나는 일 (1) 2024.01.22 [NetWork] CORS(Cross-Origin Resource Sharing) (0) 2024.01.20