JWT에 대한 이해
JWT란?
JWT(Json Web Token)는 말 그대로 웹에서 사용되는 JSON형식의 토큰에 대한 표준 규격으로 주로 사용자의 인증(authentication) 또는 인가(authorization) 정보를 서버와 클라이언트 간에 안전하게 주고 받기 위해서 사용된다.
-
Authorization(인가): 유저에 대한 권한을 허락하는 것으로 사용자가 로그인하면 이후의 각 요청에서는 JWT가 포함되어 사용자가 해당 토큰으로 허용되는 패스, 서비스 및 리소스에 액세스할 수 있도록 해준다. Single Sign On방식으로 오버헤드가 적고 여러 도메인에서 쉽게 사용할 수 있기 때문에 오늘날 JWT를 널리 사용하는 기능이다.
-
authentication(인증): 사용자가 올바른 사용자임을 확인하면 클라이언트에게 Access Token(JWT)을 발급해준다. 토큰 기반의 인증은 발급해준 후 요청이 들ㅇ오면 검증만 해주면 되기때문에 Stateless하다. 확장성이 뛰어나 토큰 기반의 다른 인증 시스템에 접근이 용이하다.
-
Sngle Sign On(SSO): 하나의 시스템(인증 서버)에서 클라이언트에 대한 인증을 수행하고, 그 인증 정보를 가지고 추가적인 인증 없이 다른 서비스들도 사용할 수 있도록 하는 기능이다. 하나의 인증 정보로 여러 서비스를 사용하기 때문에 여러 서비스에 대한 로그인 처리가 간소해지기 때문에 편리하다는 장점이 있다.
JWT의 구조
JWT는 헤더(header), 정보(payload), 서명(signature) 세 파트로 나눠져 있다. 각 파트는 점(.)으로 구분하며 각 부분은 BASE64로 인코딩 되어 표현된다.
헤더(header)
- 알고리즘으로 암호화 할 것인지, 어떠한 토큰을 사용할 것 인지에 대한 정보가 들어있다.
- typ: 토큰의 타입을 지정한다. JWT이다.
- alg: 해싱 알고리즘 방식을 지정하며, 서명(Signature) 및 토큰 검증에 사용한다.
- 해싱 알고리즘은 보통 HMAC-SHA256, RSA가 사용된다.
정보(Payload)
-
Payload 부분에는 토큰에 담을 정보가 들어있다. 정보의 한 조각을 클레임(Claim)이라고 부르고 이는 Json(Key, Valye) 형태의 한 쌍으로 이뤄져있다.
-
토큰에는 여러개의 클레임을 넣을 수 있다.
-
정보는 수정이 가능하며 더 많은 정보를 추가할수 있지만 노출과 수정이 가능한 지점이기 때문에 인증이 필요한 최소한의 정보만을 담아야한다.
-
클레임의 종류 3가지
- 비공개 클레임(Private Claim)
- 비공개 클레임은 사용자 정의 클레임으로, 클라이언트와 서버가 협의하에 임의로 지정한 정보를 저장해서 사용한다.
- 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할때에 유의해야 한다.
{
"userId": "dev-coco"
"username": "coco"
}
서명(Signauture)
- 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다.
헤더(Header)와 내용(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀키를 이용해 헤더에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
JWT의 동작원리
http://www.opennaru.com/opennaru-blog/jwt-json-web-token/
- 사용자가 id와 password를 입력하여 로그인을 요청
- 서버는 회원 DB에 들어가 있는 사용자인지 확인
- 서버는 요청을 확인하고 secret key를 통해 Access token을 발급
- JWT 토큰을 클라이언트에 전달
- 클라이언트에서 API 을 요청할때 클라이언트가 Authorization header에 Access token을 담아서 전송
- 서버는 JWT Signature를 체크하고 Payload로부터 사용자 정보를 확인해 데이터를 반환
- 클라이언트의 요청에 대한 응답 전달
- 클라이언트의 로그인 정보를 서버 메모리에 저장하지 않기 때문에 토큰기반 인증 메커니즘을 제공한다.
- 인증이 필요한 경로에 접근할 때 서버 측은 Authorization 헤더에 유효한 JWT 또는 존재하는지 확인한다.
- JWT에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스과 같은 서버와의 커뮤니케이션 오버 헤드를 최소화 할 수 있다.
- Cross-Origin Resource Sharing (CORS)는 쿠키를 사용하지 않기 때문에 JWT를 채용 한 인증 메커니즘은 두 도메인에서 API를 제공하더라도 문제가 발생하지 않는다.
- 처음 사용자를 등록할 때 Access token과 Refresh token이 모두 발급되어야 합니다.
JWT의 장점
- JWT 의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요 없다
- 거의 모든 곳에서 토큰이 생성될 수 있으며, 서버에서 토큰을 확인할 필요가 없다.
- 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라진다.
- 분산 마이크로 서비스 환경에서 중앙 집중식 인증 서버와 데이터베이스에 의존하지 않는 쉬운 인증 및 인가 방법을 제공한다.
- 내장된 기능으로 액세스 가능한 데이터, 권한 지속 시간, 로그인 시 가능한 작업을 지정할 수 있다.
- JSON 코드 언어로 생성된 토큰은 용량이 작기 때문에 트래픽 대한 부담이 낮다.
- REST 서비스로 제공 가능하다.
JWT의 단점
- 토큰은 클라이언트에 저장되어 데이터베이스에서 사용자 정보를 조작하더라도 토큰에 직접 적용할 수 없다.
- 단일 키를 이용 함으로 키가 유출되면 시스템 전체가 위험에 노출된다.
- 토큰은 이해하기가 쉽지 않아 개발자가 암호 서명 알고리즘에 잘 모른다면 자신도 모르게 시스템을 위험에 빠뜨릴 수 있다.
- 상태를 저장하지 않기 때문에 한번 만들어지면 제어가 불가능하다
- 토큰을 탈취당하면 대처하기 어렵고, 특정 토큰을 강제 만료하기 어렵다.
- Payload 자체는 암호화되지 않기 때문에 중요한 정보를 담을 수 없다.
- 토큰의 페이로드(Payload)에 3종류의 클레임을 저장하기 때문에, 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.