토큰, JWT(JSON Web Token)
- -
HTTP의 특성
토큰에 대해 알아보기 전에 HTTP의 중요한 특성을 이해하고 있어야 합니다. HTTP는 서버와 클라이언트가 데이터를 주고 받는 대표적인 통신 프로토콜 중 하나입니다. 이러한 HTTP 프로토콜은 각 연결과 상태가 독립적이라는 특성을 갖고 있습니다!
즉, HTTP는 connectionless(연결을 유지 하지 않음)하며, stateless(상태를 유지하지 않음)합니다(쉽게 말해 전에 무슨 일이 있었는지 전혀 모르고, 또 알려고도 하지 않는 특성입니다). 따라서 쿠키 또는 세션 등 이전 정보를 기억할 수 있는 추가적인 조치가 없다면, 사용자가 로그인 한 다음 페이지를 이동하면 바로 다시 로그인을 해야하는 불편한 일이 발생할 수 있습니다.
토큰
토큰(Token)은 말 그대로 동전이라는 뜻 이지만, 웹 상에서는 특정한 목적으로만 사용 가능한 동전에 일종의 권한를 주는 것을 말합니다.
토큰은 로그인 자격 증명을 반복적으로 입력하지 않고도 사용자를 인증하는 데 사용됩니다. 사용자가 웹사이트에 로그인하면 웹사이트에서 토큰을 생성하여 사용자의 브라우저로 보냅니다. 이 토큰은 사용자의 컴퓨터에 저장됩니다.
사용자가 웹사이트에 후속 요청을 하면 요청과 함께 토큰이 전송됩니다. 그런 다음 웹 사이트는 토큰을 사용하여 사용자가 요청할 때마다 로그인 자격 증명을 입력하지 않고도 사용자가 누구인지 확인할 수 있습니다.
토큰은 웹 사이트의 특정 부분에 대한 액세스를 제어하는 데에도 사용됩니다. 예를 들어 웹 사이트에 특정 사용자만 액세스할 수 있는 관리 대시보드가 있는 경우 웹 사이트는 대시보드에 대한 액세스 권한을 부여하는 토큰을 생성할 수 있습니다. 그런 다음 이 토큰을 필요한 권한이 있는 사용자에게 보낼 수 있습니다.
해싱은 암호 및 기타 민감한 데이터를 암호화하는 데 사용되는 반면 토큰은 사용자를 인증하고 웹 사이트의 특정 부분에 대한 액세스를 제어하는 데 사용됩니다. 이러한 도구를 사용하여 웹사이트는 사용자의 데이터를 안전하게 유지할 수 있습니다.
토큰의 인증방식
- 사용자가 인증 정보를 담아 서버에 로그인 요청을 보냅니다.
- 서버는 데이터베이스에 저장된 사용자의 인증 정보를 확인합니다.
- 인증에 성공했다면 해당 사용자의 인증 및 권한 정보를 서버의 비밀 키와 함께 토큰으로 암호화합니다.
- 생성된 토큰을 클라이언트로 전달합니다.
- HTTP 상에서 인증 토큰을 보내기 위해 사용하는 헤더인 Authorization 헤더를 사용하거나, 쿠키로 전달하는 등의 방법을 사용합니다.
- 클라이언트는 전달받은 토큰을 저장합니다.
- 저장하는 위치는 Local Storage, Session Storage, Cookie 등 다양합니다.
- 클라이언트가 서버로 리소스를 요청할 때 토큰을 함께 전달합니다.
- 토큰을 보낼 때에도 Authorization 헤더를 사용하거나 쿠키로 전달할 수 있습니다.
- 서버는 전달받은 토큰을 서버의 비밀 키를 통해 검증합니다. 이를 통해 토큰이 위조되었는지 혹은 토큰의 유효 기간이 지나지 않았는지 등을 확인할 수 있습니다.
- 토큰이 유효하다면 클라이언트의 요청에 대한 응답 데이터를 전송합니다.
토큰을 왜 사용할까?
세션 기반 인증도 있는데 토큰 기반 인증 시스템을 선택하는데에는 여러가지 이유
- Stateless
토큰 기반 인증은 서버에서 사용자의 정보를 가지지 않기 때문에 무상태성을 가져서 서버가 확장을 하여도 문제가 생기지 않게 됩니다.
상태를 가지는 세션을 사용하는 방식에서 서버를 확장한다면 사용자가 로그인 했을 때, 유저는 처음 로그인한 서버에만 요청하는 문제가 발생할 수 있습니다. 하지만 토큰을 사용하게 되면 어떠한 서버로 요청이 가도 상관이 없게 됩니다. - 모바일 어플리케이션에 적합합니다
Android나 iOS 모바일 어플리케이션을 개발할 때, 안전한 API 를 만들기 위해서는 쿠키 컨테이너를 사용해야 하는 쿠키같은 인증시스템은 이상적이지 않습니다. 만약 토큰 기반 인증을 도입한다면 더욱 간단하게 이 번거로움을 해결 할 수 있게 됩니다. - 인증정보를 다른 어플리케이션으로 전달합니다
대표적인 예제로 OAuth 가 있다. 페이스북/구글 같은 소셜 계정들을 이용하여 다른 웹서비스에서도 로그인 할 수 있게 합니다. - 보안
토큰 기반 인증 시스템을 사용하여 어플리케이션의 보안을 높일 수 있습니다. 단, 이 토큰 기반 인증을 사용한다고 해서 무조건 해킹의 위험에서 벗어나는건 아닙니다.
웹사이트에 로그인하는 사용자가 페이지를 이동할 때마다 새롭게 로그인해야 한다면 불편할 뿐더러 개인 정보가 유출될 수 있는 위험이 존재합니다. 웹에서 로그인을 처리하는 대표적인 방법으로는 세션 방식과 토큰 방식이 있으며, 다음과 같은 차이점이 존재합니다.
- 세션 방식: 서버의 메모리 또는 데이터베이스 등에 사용자의 정보를 저장하는 방식입니다. 서버는 사용자를 확인한 다음 세션 ID를 발급합니다. 토큰 방식에 비해 보안이 좋으나 서버의 자원이 상대적으로 많이 필요합니다.
- 토큰 방식: 서버에서 발행하는 토큰을 사용자의 브라우저에 저장하는 방식입니다. 세션 방식에 비해 트래픽에 대한 부담이 적으나, 토큰이 유출될 경우 누구나 정보를 확인할 수 있어 보안이 상대적으로 떨어집니다. 또한 토큰에 담기는 데이터 크기가 길어지므로 잦은 요청 시 데이터 트래픽에 영향을 미칠 수 있습니다.
세션 기반 인증에서 서버는 사용자가 로그인한 후 각 사용자에 대한 세션을 생성합니다. 이 세션은 서버에 저장되고 클라이언트 브라우저의 쿠키에 저장된 세션 ID로 식별됩니다. 후속 요청이 있을 때마다 클라이언트는 세션 ID 쿠키를 서버로 보내고 서버는 이를 사용하여 사용자의 세션을 조회하고 인증 정보를 검색합니다.
토큰 기반 인증에서는 인증에 성공하면 토큰이 생성되어 사용자에게 발급됩니다. 이 토큰은 세션 ID 쿠키 대신 후속 요청을 인증하는 데 사용됩니다. 토큰은 일반적으로 JWT(JSON Web Token)이며 사용자의 인증 정보와 유효성을 보장하는 암호화 서명이 포함되어 있습니다.
토큰 기반 인증의 장점 중 하나는 상태 비저장이라는 것입니다. 이것은 서버가 세션 상태를 저장할 필요가 없다는 것을 의미하며, 이는 확장성을 향상시키고 세션 관리와 관련된 버그의 가능성을 줄일 수 있습니다. 또한 토큰에는 필요한 모든 인증 정보가 포함되어 있으므로 API 및 기타 상태 비저장 서비스에서 토큰 기반 인증을 사용할 수 있습니다.
토큰 기반 인증의 또 다른 장점은 세션 기반 인증보다 더 안전하다는 것입니다. 강력한 암호화 알고리즘을 사용하여 토큰을 암호화하고 서명할 수 있으므로 공격자가 토큰을 위조하거나 조작하기 어렵습니다. 반대로 세션 ID는 일반적으로 공격자가 쉽게 훔칠 수 있는 쿠키에 저장됩니다.
마지막으로 토큰 기반 인증은 세션 기반 인증보다 더 유연합니다. 토큰은 모바일 앱 및 단일 페이지 애플리케이션을 포함하여 다양한 클라이언트의 요청을 인증하는 데 사용할 수 있습니다. 또한 토큰에는 사용자 역할이나 권한과 같은 인증 데이터 이외의 추가 정보가 포함될 수 있습니다.
전반적으로 토큰 기반 인증은 확장성, 보안 및 유연성을 포함하여 세션 기반 인증에 비해 몇 가지 이점을 제공합니다.
JWT 란?
토큰 기반 인증 구현 시 대표적으로 사용하는 기술로 JWT(JSON Web Token)가 있습니다. JWT는 JSON 객체에 정보를 담고 이를 토큰으로 암호화하여 전송할 수 있는 기술이며 웹 어플리케이션에서 사용되는 인증과 권한 부여를 위한 표준 방식 중 하나입니다. JWT는 클라이언트와 서버 간의 정보를 안전하게 전송하기 위해 사용됩니다.
JWT는 세 부분으로 구성됩니다. Header, Payload, Signature 입니다.
- Header에는 JWT의 유형과 사용하는 암호화 알고리즘 등이 저장되어 있습니다.
- Payload는 클라이언트와 서버 간에 공유되는 정보가 저장되어 있습니다.
- Signature는 암호화된 Header와 Payload를 검증할 수 있는 값을 포함하고 있습니다.
헤더(header)
헤더에는 JWT를 검증하는 암호화 알고리즘, 토큰 타입 등이 포함됩니다.
{
"alg": "HS256",
"typ": "JWT"
}
페이로드(payload)
토큰에 담아 전송하는 데이터가 포함됩니다. 이러한 각 정보를 클레임(claim)이라 하며, 이는 키-값으로 구성되어 있습니다. 클레임은 사전 정의된 registered clam, 개발자가 정의한 public claim, 두 주체 간에만 교환되는 기타 private claim으로 구분됩니다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
헤더와 페이로드는 데이터를 16진수로 인코딩하는 것이며 암호화를 진행하는 것이 아닙니다. 따라서 누구나 이를 디코딩하여 정보를 확인할 수 있습니다. 즉, JWT에 담아 전달하는 값에는 민감한 정보를 담지 않아야 합니다.
서명(signature)
서명을 위해서는 인코딩된 헤더와 페이로드, 시크릿 키, 알고리즘이 필요합니다. 서명을 통해 토큰을 인코딩 된 당시의 환경과 대조할 수 있으며, 진위 여부를 확인할 수 있습니다.
access_token = jwt.encode({
"sub": "1234567890",
"name": "John Doe",
"admin": true
}, SECRET_KEY, algorithm='HS256')
이러한 세 부분을 모두 조합하면 다음과 같은 JWT 토큰이 생성됩니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao
JWT는 왜 사용할까?
JWT는 쿠키와 같은 기존 세션 기반 인증 방법의 제한 사항을 해결하기 위해 만들어졌습니다. 쿠키를 사용하여 서버는 클라이언트 측에 세션 데이터를 저장하므로 XSS(교차 사이트 스크립팅) 및 CSRF(교차 사이트 요청 위조)와 같은 보안 취약점이 발생할 수 있습니다. 반면에 JWT는 세션 데이터를 서버 측에 저장하고 이를 토큰으로 전송하므로 더 안전하고 공격에 덜 취약합니다.
JWT는 웹 애플리케이션, 특히 마이크로서비스를 사용하거나 분산 아키텍처가 있는 애플리케이션에서 자주 사용됩니다. 여러 시스템 또는 서비스에서 인증 및 권한 부여가 필요한 상황에서 사용하면 좋습니다. 토큰에는 필요한 모든 정보가 포함되어 있으므로 지속적인 인증 요청 없이 서비스 간에 전달할 수 있습니다.
정리하자면 JWT는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 표준입니다. 기존 세션 기반 인증 방법의 한계를 해결하기 위해 만들어졌으며 최신 웹 애플리케이션, 특히 분산 아키텍처가 있는 애플리케이션에서 자주 사용됩니다. JWT는 여러 시스템 또는 서비스에서 인증 및 승인이 필요한 상황에서 사용하기에 좋습니다.
다양한 유형의 토큰
토큰은 사용자 ID를 확인하는 데 사용할 수 있는 데이터 아티팩트입니다. 토큰을 디지털 서명으로 생각할 수 있습니다. 개발자가 승인에 사용할 수 있는 두 가지 기본 유형의 토큰이 있습니다.
- ID Token
- ID 토큰은 특히 OAuth 2.0 및 이와 가까운 OIDC(Open ID Connect)(SSO( Single Sign On) 인증 흐름 에서 일반적임 )와 관련이 있습니다. 여기에서 자세히 다루지는 않겠지만 이러한 거래에서 ID 토큰은 사용자가 로그인할 때마다 발급됩니다. 여기에는 사용자 이름, 이메일 또는 중요할 수 있는 기타 요소와 같은 정보가 포함됩니다. SSO 인증 프로세스에서 ID 토큰은 사용자의 신원이 진짜인지 확인합니다.
- Access Token
- 액세스 토큰은 사용자가 보안 API와 같은 보호된 리소스에 액세스하기 위한 자격 증명입니다. 이러한 토큰은 권한 부여 서버에서 발급되며 일반적으로 수명이 짧습니다(분 또는 시간). 액세스 토큰이 만료되면 사용자는 새 액세스 토큰을 받으려면 다시 인증해야 합니다.
- Refresh Token
- 새로 고침 토큰은 더 긴 수명(주, 월, 년, 심지어 무한)을 가지며 현재 액세스 토큰이 만료될 때 인증 서버에서 새 액세스 토큰을 자동으로 요청하는 데 사용됩니다. 새로 고침 토큰 자체로는 사용자에게 액세스 권한을 제공하지 않는다는 점에 유의해야 합니다.
Refresh token이란?
일반적인 웹 애플리케이션에서 액세스 토큰은 수명이 제한되어 있으며 일정 기간이 지나면 만료됩니다. 액세스 토큰이 만료되면 사용자는 새 액세스 토큰을 얻기 위해 다시 로그인해야 합니다. 이는 로그인 자격 증명을 여러 번 다시 입력해야 할 수 있으므로 사용자에게 불편할 수 있습니다.
이 문제를 해결하기 위해 많은 웹 애플리케이션에서 JWT 새로 고침 토큰을 사용합니다. 새로 고침 토큰은 사용자가 로그인할 때 생성되는 별도의 토큰으로 현재 액세스 토큰이 만료되면 새 액세스 토큰을 얻는 데 사용됩니다. 새로 고침 토큰은 일반적으로 액세스 토큰보다 수명이 길고 클라이언트 측에 안전하게 저장됩니다.
액세스 토큰이 만료되면 클라이언트 애플리케이션은 새로 고침 토큰을 사용하여 서버에서 새 액세스 토큰을 요청할 수 있습니다. 서버는 새로 고침 토큰의 유효성을 검사하고 새 액세스 토큰을 생성한 다음 클라이언트 애플리케이션으로 다시 보냅니다.
액세스 토큰과 새로 고침 토큰의 관계는 다음과 같이 생각할 수 있습니다. 액세스 토큰은 보호된 리소스에 액세스하는 데 사용되며 수명이 짧고 새로 고침 토큰은 새 액세스 토큰을 얻는 데 사용되며 수명이 더 깁니다.
Refresh token 은 어떻게 만들어지나요?
Refresh Token은 Access Token 발급과 동시에 Authorization Server에서 생성됩니다. 사용자가 애플리케이션에 로그인하면 사용자, 권한 부여 서비스 및 리소스 서버 간에 다음 시퀀스가 시작됩니다.
- 사용자가 인증 프로세스를 성공적으로 완료합니다.
- 인증 서버는 사용자에게 액세스 토큰(Access Token)과 갱신 토큰(Refresh Token)을 제공합니다.
- 사용자는 리소스 서버에 액세스 토큰(Access Token)을 제공합니다.
- 리소스 서버는 액세스 토큰(Access Token)의 유효성을 검사한 다음 사용자에게 보호된 리소스에 대한 액세스 권한을 제공합니다.
- 액세스 토큰이 만료되면 사용자는 인증 서버에 갱신 토큰(Refresh Token)을 제공합니다.
- 인증 서버는 새로 고침 토큰의 유효성을 검사한 다음 사용자에게 새 액세스 토큰(Access Token)을 제공합니다.
- 사용자는 인증 프로세스를 다시 시작하지 않고 액세스를 유지하기 위해 리소스 서버에 새 액세스 토큰을(Access Token) 제공합니다.
'프론트엔드 공부 > Web Server' 카테고리의 다른 글
리플로우(Reflow)와 리페인트(Repaint) (0) | 2023.04.10 |
---|---|
OAuth이란? (0) | 2023.03.09 |
Hashing (0) | 2023.03.08 |
세션(블로깅중) (0) | 2023.03.07 |
쿠키란 무엇일까? 개념, 필요성, 속성, 문제점 (0) | 2023.03.07 |
소중한 공감 감사합니다