JWT 인증방식

공룡개발자·2022년 3월 13일
0
post-custom-banner

1. HTTP(HyperText Transfer Protocol)

텍스트 기반의 통신규약으로 비연결성(Connectionless)와 무상태성(Stateless)을 특징으로 지닌다. 즉, 클라이언트 측의 요청이 서버에 닿아, 서버가 응답을 마치면 기록이나 연결을 끊어버리게 된다. 어쩌면 당연한 것이, 수억명의 유저의 활동을 기억하게 되면 상당한 자원 낭비를 피할 수 없으니 말이다.

그러나 HTTP의 특징은 다른 말로 서버가 클라이언트를 식별하지 못하게 된다는 것이다. 단적으로 로그인을 하더라도 해당 클라이언트를 기억하지 못하게 되는 것처럼 말이다.

이러한 HTTP의 결점은 Cookie와 Sesstion을 통해 보완된다.

2. Cookie

쿠키는 클라이언트가 특정 웹사이트에 방문해 서버에 요청을 보낼 때, 서버의 응답과 함께 그 응답에 관한 정보를 담은 작은 텍스트 파일이다. 이후 클라이언트의 또다른 요청이 수행될 때 서버 측으로부터 받은 쿠키를 동봉?함으로써 특정 클라이언트의 정보를 전달한다. 쉽게 말하자면 놀이동산 매표소에서 자유이용권을 구매하고 각각의 놀이기구를 타기 전에 해당 자유이용권을 통해 자격을 확인받는 것과 비슷하다.

하지만 이러한 방식은 몇몇 단점을 지니게 되는데, 요청 시 쿠키의 값을 그대로 보내기 때문에 유출 및 조작의 위험이 동반된다. 또한 쿠키는 용량 제한이 있어 많은 정보를 담을 수 없고, 쿠키의 정보량이 커지면 네트워크의 부담을 초래한다.

3. Cookie & Session

쿠키의 유출 및 조작의 위험으로 비밀번호와 같은 인증정보를 쿠키에 담아 열린 공간인 HTTP에 전달하는 것은 상당히 위험하다.

그래서 세션은 동일하게 클라이언트의 요청에 대한 응답으로 쿠키를 이용하지만, 유출되면 안되는 인증정보는 따로 서버에 저장해 쿠키에는 클라이언트 식별자인 JSESSIONID(쉽게는 이름표?)를 함께 담아 보낸다.

그래서 쿠키가 유출이 되더라도 클라이언트 인증정보는 빈껍데기인 JSESSIONID로만 남아있어 해커가 유의미한 정보를 탈취할 수 없게 된다.

그러나 클라이언트마다 새로운 고유 세션ID를 발급하고 요청마다 JSESSIONID를 통해 식별해야 하기때문에 요청이 폭주하면 서버의 부하가 심해진다.

4. JWT 기반 인증

그렇다면 쿠키처럼 간편하게 사용되지만 해킹의 위험이 적고, 세션처럼 안전하지만 서버에 인증정보를 저장하지 않는 인증 방식은 없을까?

그것이 JWT 기반 인증이다. JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 토큰으로 쿠키와 세션 방식과 유사하게 HTTP 헤더에 실어 서버가 클라이언트를 식별한다.

클라이언트에서 로그인 요청을 보내면 서버는 해당 유저 정보를 토큰에 담고 이 위에 사인해서 전달한다. 이 후 또다른 요청과 함께 사인된 토큰이 도착하면 서버는 그 사인이 유효한지 검증 후 응답을 보내게 된다.

JWT에서 서버가 하는 일은 그 토큰이 유효한지 아닌지 식별하는 것일뿐이다.

카카오톡 QR코드가 대표적인 예이다.

4.1. JWT 구조


JWT는 .을 구분자로 header.payload.signature로 구성된 조합이다.

  • Header
{
	"alg": 'HS256",
    "typ": 'JWT'
}

Header는 alg과 typ은 각각 정보를 암호화할 해싱 알고리즘 및 토큰의 타입을 지정합니다.

  • Payload
{
	"sub": '1234567899",
    "name": 'John',
    "iat": 1234532532
}

Payload는 토큰에 담을 정보를 지니고 있다. 주로 클라이언트의 고유 ID 값 및 유효 기간 등이 포함되는 영역이다.

  • Signature
    Signature는 인코딩된 Header와 Payload를 더한 뒤 비밀키로 해싱하여 생성한다.
    Header와 Payload는 단순히 인코딩된 값이기 때문에 제 3자가 복호화 및 조작할 수 있지만, Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화할 수 없습니다. 따라서 Signature는 토큰의 위변조 여부를 확인하는데 사용됩니다.

  • 인증 과정

  1. 클라이언트 로그인 요청이 들어오면, 서버는 검증 후 클라이언트 고유 ID 등의 정보를 Payload에 담습니다.
  2. 암호화할 비밀키를 사용해 Access Token(JWT)을 발급합니다.
  3. 클라이언트는 전달받은 토큰을 저장해두고, 서버에 요청할 때 마다 토큰을 요청 헤더 Authorization에 포함시켜 함께 전달합니다.
  4. 서버는 토큰의 Signature를 비밀키로 복호화한 다음, 위변조 여부 및 유효 기간 등을 확인합니다.
  5. 유효한 토큰이라면 요청에 응답합니다.
  • 장점
  1. Header와 Payload를 가지고 Signature를 생성하므로 데이터 위변조를 막을 수 있습니다.
  2. 인증 정보에 대한 별도의 저장소가 필요없습니다.
  3. JWT는 토큰에 대한 기본 정보와 전달할 정보 및 토큰이 검증됬음을 증명하는 서명 등 필요한 모든 정보를 자체적으로 지니고 있습니다.
  4. 클라이언트 인증 정보를 저장하는 세션과 다르게, 서버는 무상태가 됩니다.
  5. 확장성이 우수합니다.
  6. 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능합니다.
  7. OAuth의 경우 Facebook, Google 등 소셜 계정을 이용하여 다른 웹서비스에서도 로그인을 할 수 있습니다.
  8. 모바일 어플리케이션(네이티브 앱) 환경에서도 잘 동작합니다.
  • 단점
  1. 쿠키/세션과 다르게 JWT는 토큰의 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해집니다.
  2. Payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보는 담을 수 없습니다. 사용자 관리에 있어 한계가 있다.
  3. 토큰을 탈취당하면 대처하기 어렵습니다.
  4. 토큰은 한 번 발급되면 유효기간이 만료될 때 까지 계속 사용이 가능하기 때문입니다.
  5. 특정 사용자의 접속을 강제로 만료하기 어렵지만, 쿠키/세션 기반 인증은 서버 쪽에서 쉽게 세션을 삭제할 수 있습니다.

간략정리

  1. 쿠키: 그냥 옮기는 시스템. 매개체
  2. 토큰: 서버가 기억하는 이상하게 생긴 텍스트. ID 카드처럼 서버에게 보여줘야 하는 것.
  3. JWT: 정보를 갖고있는 토큰. DB없이 검증할 수 있음.

참고

https://www.youtube.com/watch?v=tosLBcAX1vk
http://www.opennaru.com/opennaru-blog/jwt-json-web-token/
https://lovefor-you.tistory.com/247

profile
공룡의 발자취
post-custom-banner

0개의 댓글