Node

[Node.js] JWT에 대하여 알아보기

YaluStar 2023. 9. 7. 22:12

안녕하세요.

이번에는 JWT에 대하여 알아보겠습니다.

 

1. JWT (JSON Web Token)

JSON 웹 토큰(JSON Web Token, JWT)은 선택적 서명 및 선택적 암호화를 사용하여 데이터를 만들기 위한 인터넷 표준으로, 페이로드는 몇몇 클레임(claim) 표명(assert)을 처리하는 JSON을 보관하고 있다.
토큰은 비공개 시크릿 키 또는 공개/비공개 키를 사용하여 서명된다. 이를테면 서버는 "관리자로 로그인됨"이라는 클레임이 있는 토큰을 생성하여 이를 클라이언트에 제공할 수 있다. 그러면 클라이언트는 해당 토큰을 사용하여 관리자로 로그인됨을 증명한다.
이 토큰들은 한쪽 당사자의 비공개 키(일반적으로 서버의 비공개 키)에 의해 서명이 가능하며 이로써 해당 당사자는 최종적으로 토큰이 적법한지를 확인할 수 있다. 일부 적절하고 신뢰할만한 수단을 통해 다른 당사자가 상응하는 공개키를 소유하는 경우 이 경우 또한 토큰의 적법성 확인이 가능하다.
토큰은 크기가 작고 URL 안전으로 설계되어 있으며 특히 웹 브라우저 통합 인증(SSO) 컨텍스트에 유용하다. JWT 클레임은 아이덴티티 제공자와 서비스 제공자 간(또는 비즈니스 프로세스에 필요한 클레임)의 인가된 사용자의 아이덴티티를 전달하기 위해 보통 사용할 수 있다.

- 출처 : 위키백과 -

 

=> 쉽게 정리하자면 사용자의 인증(authentication) 또는 인가(authorization) 정보를 클라이언트와 서버 간에 안전하게 주고받기 위해서 사용됩니다.

 

2. JWT 구조

2-1. 헤더 (Header)

{
 "alg" : "HS256",
 "typ" : "JWT"
}

서명 생성을 위해 어느 알고리즘을 사용할지를 식별한다
HS256는 이 토큰이 HMAC-SHA256를 사용하여 서명됨을 의미한다.
일반적으로 쓰이는 암호화 알고리즘들은 SHA-2(HS256) 방식의 HMAC와 SHA-256(RS256) 방식의 RSA 서명이다. JWA(JSON 웹 알고리즘) RFC 7518은 인가 및 암호화를 위해 더 많은 것을 도입하고 있다

 

2-2. 페이로드 (Payload)

{
 "loggedInAs" : "admin",
 "iat" : 1422779638
}

일련의 클레임을 포함한다. JWT 사양은 토큰에 일반적으로 포함되는 표준 필드인 7개의 등록 클레임 이름(Registered Claim Names)을 정의한다.
토큰의 목적에 따라 사용자 지정 클레임 또한 일반적으로 포함된다.
다음 예는 표준 Issued At Time 클레임(iat)과 사용자 지정 클레임(loggedInAs)을 보여준다.

 

  • Registed claims : 미리 정의된 클레임
    • iss(issuer; 발행자),
    • exp(expireation time; 만료 시간),
    • sub(subject; 제목),
    • iat(issued At; 발행 시간),
    • jti(JWI ID)

 

  • Public claims : 사용자가 정의할 수 있는 클레임 공개용 정보 전달을 위해 사용
  • Private claims : 해당하는 당사자들 간에 정보를 공유하기 위해 만들어진 사용자 지정 클레임. 외부에 공개돼도 상관없지만 해당 유저를 특정할 수 있는 정보들을 담는다.

 

2-3. 구조 (Signature)

HMAC-SHA256(
 secret,
 base64urlEncoding(header) + '.' +
 base64urlEncoding(payload)
)

토큰을 안전하게 확인한다. 서명은 Base64url 인코딩을 이용하여 헤더와 페이로드를 인코딩하고 이 둘을 점(.) 구분자로 함께 연결시킴으로써 계산된다.
해당 문자열은 그 뒤 헤더에 규정된 암호화 알고리즘(이번 경우에는 HMAC-SHA256)에 유입된다.
Base64url 인코딩은 base64와 비슷하지만 각기 다른 영숫자를 사용하며 패딩(padding)은 제외한다.

 

이 세 부분은 Base64url 인코딩을 사용하여 별도로 인코딩 되며 JWT 생성을 위해 점(.)을 사용하여 연결된다:

const token = base64urlEncoding(header) + '.' + base64urlEncoding(payload) + '.' + base64urlEncoding(signature)

 

위 데이터와 "secretkey" 시크릿은 토큰을 생성한다:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI

 

3. JWT 테스트 사이트

- 해당 사이트에서 JWT를 임시로 만들어 볼 수 있습니다.

 

4. 사용

인증의 경우 사용자가 성공적으로 자신들의 자격 정보를 사용하여 로그인하면 JSON 웹 토큰이 반환되며 로컬(일반적으로 로컬 또는 세션 스토리지. 쿠키를 사용할 수도 있음)에 저장되어야 한다. 부재중인 프로세스의 경우 클라이언트는 미리 공유된 시크릿으로 자신만의 JWT를 생성하고 서명하고 이를 OAuth를 준수하는 서비스에 전달함으로써 다음과 같이 직접 인증을 수행할 수도 있다.

POST /oauth2/token?
Content-type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=eyJhb...

 

클라이언트가 유효한 JWT 표명을 전달하면 서버는 애플리케이션의 요청을 하기 위한 access_token을 생성하고 클라이언트에 이를 전달해 주게 된다:

{
  "access_token": "eyJhb...",
  "token_type": "Bearer",
  "expires_in": 3600
}

 

클라이언트가 보호된 루트나 자원에 접근하고 싶은 경우 사용자 에이전트는 일반적으로 Bearer 스키마를 사용하여 Authorization 헤더 안에 JWT를 보내야 한다. 헤더의 내용은 다음과 같을 수 있다:

Authorization: Bearer eyJhbGci...<snip>...yu5CSpyHI

이것은 무상태 인증 메커니즘으로서, 사용자의 상태는 서버 메모리에 전혀 저장되지 않는다. 서버의 보호된 루트는 Authorization 헤더 내의 유효한 JWT를 검사하며 이것이 존재하는 경우 사용자는 보호된 자원으로의 접근이 허가된다. JWT가 자가 수용적(self-contained)이므로 필요한 모든 정보는 JWT에 있으며 데이터베이스를 여러 번 조회할 필요를 줄여준다.

 

 

5. JWT 인증과정

JWT 인증 과정

 

6. 장점

  • 데이터의 위변조를 방지한다.
  • JWT는 인증에 필요한 모든 정보를 담고 있기 때문에 인증을 위한 별도의 저장소가 없어도 된다.
  • 세션(Stateful)과 다르게 서버는 무상태(StateLess)가 된다.
  • 확장성이 우수하다.
  • 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능하다.(쿠키와의 차이)
  • OAuth의 경우 소셜 계정을 통해서 다른 웹서비스에 로그인할 수 있다.
  • 모바일에서도 잘 동작한다.(세션은 모바일 x)

 

7. 단점

  • 쿠키/세션과 다르게 토큰의 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해진다.
  • Payload 자체는 암호화가 되지 않아 중요한 정보는 담을 수 없다.
  • 토큰을 탈취당한다면 대처가 매우 어렵다.

 

8. 참고 사이트

 

이상으로 JWT에 대하여 알아보았습니다.

감사합니다.

 

반응형