JWT는 "JSON Web Token"의 약자로 인터넷을 통해 보안 인증 토큰을 생성하고 전송하기 위한 표준입니다.
JWT는 웹 애플리케이션 및 API에서 사용자 인증 및 권한 부여에 널리 사용됩니다.
즉, JSON으로 전자서명을 하여 URL-safe [1] 문자열로 표현한 것
[1] : URL Safe는 말 그대로 URL에 포함 할 수없는 문자를 포함하지 않는 것입니다.
인증이 필요한 경로에 접근할 때 서버 측은 Authorization 헤더에 유효한 JWT 또는 존재하는지 확인한다.
JWT에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스과 같은 서버와의 커뮤니케이션 오버 헤드를 최소화 할 수 있습니다.
Cross-Origin Resource Sharing (CORS)는 쿠키를 사용하지 않기 때문에 JWT를 채용 한 인증 메커니즘은 두 도메인에서 API를 제공하더라도 문제가 발생하지 않습니다.
일반적으로 JWT 토큰 기반의 인증 시스템은 위와 같은 프로세스로 이루어집니다.
처음 사용자를 등록할 때 Access token과 Refresh token이 모두 발급되어야 합니다.
각각의 구성요소가 . 으로 구분이 되어있다.
<Header> . <Payload> . <Signature>
Ex)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header : 토큰의 유형, 서명 알고리즘
Payload : claim[^1] 이라고 부르는 사용자의 인증/인가 정보
Signature : 헤더와 페이로드가 비밀키로 서명되어 저장
[^1]: 페이로드에 담는 정보의 한 조각을 클래임이라고 부른고, 이는 name/value 한 쌍으로 이루어져있으며, 여러개의 클레임을 넣을 수 있다.
표준스펙 상 Key의 이름은 3글자로 되어있습니다.
{
"typ": "JWT", // 토큰 타입
"alg": "HS256" // 서명 알고리즘
}
alg, zip헤더는 자동으로 설정되므로, 백에서 설정할 필요가 없다.
{
"iss": "토큰 발급자",
"sub": "토큰 제목(토큰에서 사용자에 대한 식별값)",
"aud": "토큰 대상자(클라이언트)",
"exp": "토큰 만료시간",
"nbf": "토큰 활성 날짜",
"iat": "토큰 발급 시간",
"jti": "JWT 토큰 식별자",
"token_type": "access token" // Access Token 과 Refresh Token 을 구분하기 위한 Custom Claim
}
위 표준 스펙 말고도, 커스텀한 Claim을 만들어 넣을 수 있다.
중요한 점은 페이로드에 민감한 정보를 넣지 않는것...!
헤더와 페이로드는 JSON이 인코딩 되어있을 뿐이지 암호화가 걸려있는것이 아니기 때문에 누구나 디코딩 가능하다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
`your-256-bit-secret`
)
header와 payload를 base64Url 인코딩한 결과를 마침표(.)로 연결한 후, 그 결과를 secret key와 함께 HMACSHA256 알고리즘으로 서명하는 과정을 보여줍니다.