JWT(JSON Web Token)은 웹 서비스에서 정보를 안전하게 주고 받을 때 사용한다.
JWT(JSON Web Token)는 웹에서 정보를 안전하게 전달하기 위해 컴팩트하고 자가 수용적인(자체 포함적인) 방식을 정의하는 개방향 표준이다. 주로 웹 서비스 간의 인증 및 권한 부여를 위해 사용된다 JWT는 JSON 형식을 사용하여 정보를 저장하며, 서명 또는 암호화하여 보안을 강화할 수 있다.
위와 같이 JWT는 세 부분으로 구성된다. 헤더, 내용, 서명이 '.'을 구분자로 하여 JWT 토큰 1개를 이룬다. 완성된 토큰은 다음의 형태를 가진다.
// 예시
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
더 쉽게 설명하자면 물건을 포장할 때를 생각해보자.
포장지(Header): 물건을 포장할 때 어떤 종류의 포장지를 사용할지 말해주는 부분이다. 예를 들어 "용량이 작은 포장지" 같은 정보가 있다.
물건(Payload): 실제로 포장하려는 내용물이다. 물건에 대한 정보가 들어간다. 예를 들어, "이 물건은 사과입니다" 같은 정보가 있다.
물건 포장(서명, Signature): 물건과 포장지를 조합해 실제 포장을 만드는 부분이다. 이 포장은 특별한 방법으로 봉인되어 누군가 열었을 때 봉인이 풀렸다는 것을 알 수 있다.
이렇게 만들어진 포장은 안전하게 보내질 수 있다. 받는 사람은 포장지를 확인하고 물건을 꺼내서 사용할 수 있다.
웹에서도 마찬가지로, 정보(물건)를 포장해서 보낼 때 JWT를 사용한다. 정보와 함께 "포장지"를 만들어서 보내고, 받는 쪽에서는 그 포장을 열어 정보를 확인한다. 이렇게 하면 정보가 안전하게 전달되고 확인될 수 있다.
헤더(Header)는 JWT의 타입과 사용하는 해싱 알고리즘을 지정하는 부분이다. 예를 들어 다음과 같이 구성할 수 있다.
{
"alg": "HS256",
"typ": "JWT"
}
HS256은 해시 알고리즘인 HMAC SHA 256을 의미한다.
타입의 값 JWT는 이 토큰을 JWT로 지정한다.
페이로드(Payload)는 실제로 전송하려는 정보를 포함하는 부분이다. 이는 클레임(Claim)이라 불리는 키-값 쌍으로 구성된다. 클레임은 등록된(registered) 클레임, 공개(public) 클레임, 비공개(private) 클레임으로 분류된다.
등록된 클레임(Registered Claims)은 JWT(JSON Web Token)의 페이로드 부분에 들어가는 특별한 정보들을 말한다. 이러한 정보들은 JWT 표준에 이미 정의되어 있는 것들로, 일반적으로 널리 사용되는 정보를 나타낸다.
iss(Issuer): JWT를 발급한 발급자(서버)의 식별자다. 예를 들어, "https://example.com"
같은 URL이 될 수 있다.
sub(Subject): JWT에 담긴 정보의 주체를 나타낸다. 일반적으로 사용자의 고유 식별자나 아이디가 들어간다.
aud(Audience): JWT가 사용되는 대상자(대상 서비스나 앱)을 나타낸다. 여기에 지정한 대상자만 JWT를 사용할 수 있도록 할 수 있다.
exp(Expiration Time): JWT의 만료 시간을 나타낸다. 이 시간 이후에는 JWT가 더 이상 유효하지 않다.
nbf(Not Before): JWT가 사용 가능한 시간을 나타낸다. 이 시간 이전에는 JWT를 사용할 수 없다.
iat(Issued At): JWT가 발급된 시간을 나타낸다. 보통 JWT를 생성한 시간이 들어간다.
jti(JWT ID): JWT의 고유 식별자다. 중복되지 않는 고유한 값이어야 한다. 주로 중복 사용을 방지하거나 JWT를 추적할 때 사용된다.
등록된 클레임들은 JWT의 표준에 따라 정의되어 있기 때문에, 보배는 쪽과 받는 쪽이 같은 방식으로 해석할 수 있다. 예를 들어, 만료 시간이나 발급 시간을 확인하여 JWT의 유효성을 판단하거나, 발급자 정보를 통해 신뢰할 수 있는 출처인지 확인할 수 있다.
공개 클레임(Public Claims)은 JWT(JSON Web Token)의 페이로드 부분에 들어가는 정보 중, 누구나 사용할 수 있는 정보를 말한다. 이 정보들은 JWT 표준에 따라 정의되지 않았지만, 필요에 따라 사용자가 임의로 추가할 수 있는 부분이다.
간단한 예시로 설명해보자면, 여행 가방에 여러 가지 물건을 담을 때, 가방 안에 들어가는 개인적인 물건과 누구나 볼 수 있는 물건이 있을 것이다.
공개 클레임은 마치 이 누구나 볼 수 있는 물건과 같다. 토큰의 페이로드에 필요한 정보를 추가하여 전달할 수 있는데, 예를 들어 사용자의 이름, 닉네임, 프로필 사진 URL 등이 될 수 있다. 이 정보들은 JWT 토큰을 보낸 사람과 받은 사람 사이에서 사용될 수 있다.
그러나 주의해야 할 점은, 공개 클레임은 JWT의 특정 부분을 표준에 따라 정의하는 것이 아니기 때문에 충돌이 일어날 수 있다. 다른 사람들과 토큰을 공유할 때, 중복되지 않도록 유의해야 한다.
공개 클레임은 필요한 추가 정보를 토큰에 넣어서 사용할 수 있는 유연성을 제공한다. 하지만 민감한 정보는 공개 클레임에 넣지 않고, 보안이 더 중요한 등록된 클레임이나 비공개 클레임을 사용하는 것이 좋다.
비공개 클레임(Private Claims)은 JWT(JSON Web Token)의 페이로드 부분에 들어가는 정보 중, 특정한 사람들에게만 공유되어야 하는 비공개 정보를 말한다. 이 비공개 정보는 JWT 표준에 따라 정의되지 않은 사용자 정의 정보이며, 민감한 정보를 포함할 때 유용하다.
간단한 비유를 들어보자면, 어떤 비밀 파티에 초대장을 준비할 때, 모든 사람들에게는 알려지지 않아야 하는 비밀 코드가 있을 것이다.
비공개 클레임은 마치 이런 비밀 코드와 비슷하다. 토큰의 페이로드에 담긴 정보로서, 토큰을 발행한 서버와 토큰을 받는 클라이언트 사이에서만 공유되는 정보다. 예를 들어, 사용자의 이메일 주소, 권한 정보, 결제 정보 등 민감한 정보가 비공개 클레임으로 들어갈 수 있다.
이런 민감한 정보는 보안을 위해 반드시 암호화되거나 서명되어야 한다. 그렇게 함으로써 비공개 클레임의 내용이 외부에서 볼 수 없고, 무결성을 유지할 수 있다.
비공개 클레임은 JWT의 유연성을 활용하여 민감한 정보를 안전하게 전달할 수 있도록 도와준다. 하지만 민감한 정보의 경우에는 꼭 보안 조치를 취하여 안전한 전송과 저장을 보장해야 한다.
JWT(JSON Web Token) 서명은 JWT의 무결성을 검증하기 위해 사용되는 부분이다. 서명은 헤더와 페이로드를 조합한 내용을 해싱한 뒤, 비밀 키를 이용하여 서명하는 과정을 말한다. 이 서명을 통해 토큰이 변조되지 않았는지 확인할 수 있다.
헤더와 페이로드 조합: 먼저 JWT의 헤더와 페이로드를 합친 문자열을 만든다. 이 문자열은 서명에 사용될 데이터다.
해싱: 위에서 만든 문자열을 선택해서 해시 알고리즘(예: HMAC SHA-256)을 사용하여 해싱한다. 해싱은 입력 데이터를 고정된 길이의 문자열로 바꾸는 과정이다.
비밀 키 사용: 이 해시된 데이터를 비밀 키(시크릿 키)로 서명한다. 비밀 키는 JWT를 발행한 서버만 알고 있는 키다.
서명 생성: 이 과정을 통해 생성된 서명은 JWT 토큰에 추가된다. 이제 서명은 토큰의 무결성을 보장한다.
받는 쪽에서는 다음과 같은 과정을 통해 토큰의 유효성을 검증한다.
헤더와 페이로드 조합: 받은 JWT의 헤더와 페이로드를 합친 문자열을 만든다.
해싱: 위에서 만든 문자열을 같은 해시 알고리즘으로 해싱한다.
비밀 키 사용: 받는 쪽도 같은 비밀 키를 사용하여 서명을 생성한다.
서명 검증: 생성된 서명과 받은 JWT의 서명을 비교하여 두 값이 일치하는지 확인한다. 일치하지 않으면 토큰이 변조되었다는 뜻이므로 검증 실패로 처리한다.
JWT의 서명은 토큰의 변조를 막기 위한 중요한 부분이다. 서버는 토큰을 발행할 때 사용한 비밀 키를 안전하게 관리해야 하며, 토큰을 받는 쪽에서도 서명을 검증하는 과정을 통해 토큰의 무결성을 확인할 수 있다.
JWT의 작동 방식은 다음과 같다.
사용자가 자격 증명을 제공하여 로그인 요청을 한다.
서버는 이를 검증하고, 사용자의 정보를 기반으로 JWT를 생성한다.
사용자에게 JWT가 제공된다.
이후 사용자가 보호된 리소스에 접근할 때마다 JWT를 함께 제공한다.
서버는 JWT의 서명을 검증하여 사용자의 신원을 확인하고, 필요한 정보를 추출한다.
JWT의 장점은 클라이언트와 서버 간의 세션 상태를 유지할 필요 없이 정보를 안전하게 전달할 수 있다는 점이다. 그러나 보안을 위해 반드시 HTTPS를 사용하거나, 민감한 정보를 포함하지 않도록 주의해야 한다.
엑세스 토큰(Access Token)은 주로 웹 애플리케이션에서 사용자 인증과 권한 부여를 위해 사용되는 보안 토큰이다. 엑세스 토큰은 특정 리소스에 접근하는 권한을 나타내며, 사용자가 서비스나 애플리케이션에 로그인한 후에 발급되어 사용된다.
간단하게 말하면, 엑세스 토큰을 로그인한 사용자가 서비스에서 어떤 일을 할 수 있는 권한을 가지고 있다는 것을 나타내는 열쇠와 같은 역할을 한다.
다음은 엑세스 토큰의 중요한 개념이다.
인증과 권한 부여: 사용자가 로그인할 때, 서버는 사용자의 신원을 확인하고 그에 따라 해당 사용자에게 엑세스 토큰을 발급한다. 이 토큰은 사용자의 인증(로그인) 정보를 나타내며, 이를 기반으로 사용자에게 어떤 리소스나 기능에 접근할 수 있는 권한이 있는지 결정된다.
유효 기간: 엑세스 토큰은 일정한 유효 기간을 가지며, 일반적으로 짧은 시간동안만 유효하다. 이 기간 내에만 엑세스 토큰을 사용할 수 있으며, 만료된 경우 다시 로그인해야 한다.
토큰 기반 인증: 엑세스 토큰을 사용하는 시스템은 토큰을 클라이언트(웹 앱, 모바일 앱 등)가 서버에 보내 인증을 수행하고, 그에 따른 권한 부여를 받을 수 있도록 한다. 이를 토큰 기반 인증(Token-Based Authentication)이라고 한다.
보안: 엑세스 토큰은 보안을 위해 암호화되거나 서명될 수 있다. 이를 통해 토큰이 조작되거나 위조되지 않도록 보호된다.
엑세스 토큰은 OAuth나 OpenID Connect와 같은 프로토콜을 사용하여 발급되고 관리된다. 주로 웹 애플리케이션에서 API에 접근하거나 사용자의 데이터를 처리할 때 사용되며, 보안과 사용자 경험을 개선하는 데 큰 역할을 한다.
리프레시 토큰(Refresh Token)은 엑세스 토큰(Access Token)의 유효 기간이 만료되었을 때, 새로운 엑세스 토큰을 얻기 위해 사용되는 토큰이다. 리프레시 토큰은 주로 보안적인 이유로 인해 엑세스 토큰의 유효 기간을 짧게 설정하거나, 장기간 사용되어서는 안되는 경우에 활용된다.
간단하게 설명하자면, 리프레시 토큰은 만료된 엑세스 토큰을 대신해서 새로운 엑세스 토큰을 얻기 위한 열쇠와 같은 역할을 한다.
리프레시 토큰의 주요 특징은 다음과 같다.
장기 보관: 리프레시 토큰은 일반적으로 엑세스 토큰보다 더 긴 유효 기간을 가진다. 이로써 사용자가 자주 로그인할 필요 없이, 리프레시 토큰을 사용해 새로운 엑세스 토큰을 얻을 수 있다.
보안: 리프레시 토큰은 사용자의 인증 정보보다 더 중요하며, 반드시 안전한 장소에 저장되어야 한다. 보안적인 이유로 인해 클라이언트 앱에서는 리프레시 토큰에 직접 접근하지 않도록 하는 것이 좋다.
새로운 엑세스 토큰 발급: 만료된 엑세스 토큰으로부터 새로운 엑세스 토큰을 발급 받는 과정은 클라이언트가 리소스 서버나 인증 서버에 리프레시 토큰과 함께 요청을 보내는 것으로 이루어진다. 리프레시 토큰을 통해 인증을 수행하고, 새로운 엑세스 토큰을 받을 수 있다.
리프레시 토큰은 주로 OAuth 2.0 프로토콜과 관련하여 사용된다. 사용자의 편의성과 보안을 함께 고려하여 엑세스 토큰과 리프레시 토큰을 적잘하게 관리하는 것이 중요하다.
참고
JWT란 무엇인가? 그리고 어떻게 사용하는가? (1) - 개념
JWT란 무엇인가? 그리고 어떻게 사용하는가? (2) - 사용처