🔥 학습목표
- 토큰의 개념을 이해할 수 있다.
- 쿠키/세션 방식과 토큰 방식의 차이를 이해할 수 있다.
- JWT의 작동원리에 대해 이해할 수 있다.
- 토큰 방식의 한계를 이해할 수 있다.
토큰 인증은 최근 웹 애플리케이션에서 많이 사용되는 인증 방식 중 하나이다.
토큰을 사용하면 사용자의 인증 정보를 서버가 아닌 클라이언트 측에 저장할 수 있다.
세션 기반 인증은 서버에서 유저의 상태를 관리하므로 서버의 부담이 존재한다.
따라서 유저의 인증 상태를 클라이언트에 저장해 서버 부하나 메모리 부족 문제를 해결한다.
Authorization
헤더를 사용하거나, 쿠키로 전달한다. 나는 지난 프로젝트에서 로컬 스토리지에 저장한 기억이 난다.무상태성
: 서버가 유저의 인증 상태를 관리하지 않는다. 서버는 클라이언트에서 보낸 토큰의 유효성만 검증하면 되기 때문에 무상태적인 아키텍처를 구축할 수 있다.
확장성
: 다수의 서버가 공통된 세션 데이터를 가질 필요가 없다. 서버의 확장이 더욱 용이하다.
어디서나 토큰 생성 가능
: 토큰이 생성/검증이 하나의 서버에서 이루어지지 않아도 되기 때문에 토큰 생성만을 담당하는 서버를 구축할 수 있다. 여러 서비스 간 공통된 인증 서버를 구현할 수 있다.
권한 부여에 용이
: 토큰은 인증 상태, 접근 권한 등 다양한 정보를 담을 수 있어 사용자 권한 부여에 용이하다. 어드민 권한 부여 및 접근 범위도 설정할 수 있다.
JSON 객체에 정보를 담고 이를 토큰으로 암호화하여 전송할 수 있는 기술
Header
: HTTP 헤더처럼 해당 토큰 자체를 설명하는 데이터가 담겨있다. 토큰의 종류, 시그니처를 만들 때 사용할 알고리즘을 JSON 형태로 작성한다.
{
"alg": "HS256",
"typ": "JWT"
}
Payload
: HTTP 페이로드와 마찬가지로 전달하려는 내용물을 담고있는 부분이다. 접근 권한, 유저의 개인정보, 토큰 발급 시간 및 만료 시간 등의 정보들을 JSON 형태로 담는다.
{
"sub": "someInformation",
"name": "phillip",
"iat": 151623391
}
Signature
: 토큰의 무결성을 확인할 수 있는 부분이다. Header와 Payload가 완성된 경우 Signiture는 이를 서버의 비밀키와 Header에서 지정한 알고리즘을 사용해 해싱한다.
시그니처로 위조된 토큰을 알아낼 수 있더라도 토큰 자체가 탈취되면 토큰 인증 방식 또한 보안에 한계가 드러난다.
인증 상태를 관리하는 주체가 서버가 아니므로 토큰이 탈취 되더라도 해당 토큰을 강제로 만료시킬 수 없다. 해커는 토큰이 만료될 때까지 사용자로 가장해 계속해서 요청을 보낼 수 있다.
토큰이 탈취되는 상황을 대비해 유효 기간을 짧게 설정하면 사용자는 재로그인을 진행해야 하므로 귀찮아진다. 그렇다고 유효 기간을 길게 설정하면 토큰이 탈취될 경우 치명적인 약점이 될 수 있다.
토큰에 여러가지 정보를 담는 만큼 암호화 하는 과정도 길어지고 토큰의 크기도 커진다. 네트워크 비용 문제를 발생시킨다...
서버에 접근하기 위한 토큰
보안을 위해 보통 24시간 정도의 짧은 유효기간이 설정되어 있다.
액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받기 위해 사용되는 토큰
접근을 위한 토큰이 아닌 액세스 토큰을 재발급 받기 위한 토큰이므로 보다 긴 유효기간을 설정한다.
그러나 리프레시 토큰 마저도 탈취된다면 해커가 리프레시 토큰 유효 기간 동안 계속해서 액세스 토큰을 생성할 것이다. 뭐든 완벽한 보안은 없는 것인가...
그러한 문제를 해결하기 위해 리프레시 토큰을 세션처럼 서버에 저장하고 이에 대한 상태를 관리하는 방법도 있다고 한다.
그렇다면 또 세션의 단점을 보완하려던 것과 달리 또 서버가 상태를 관리하게 된다. 뭐든 정답은 없으며 보안과 사용자 경험 사이의 적절한 균형을 찾는 게 중요하다.