[JWT] Cookie, Session, JWT

Donghoon Jeong·2023년 11월 6일
0

JWT

목록 보기
1/4
post-thumbnail

1. HTTP

HTTP는 인터넷에서 데이터를 주고받는 데 사용되는 서버/클라이언트 모델을 기반으로 한 프로토콜입니다. 클라이언트가 서버에게 데이터 요청을 보내면, 서버는 이에 대한 응답을 보내어 데이터 교환이 이루어집니다. HTTP의 핵심 특성은 비연결성무상태성입니다.

비연결성(Connectionless)

  • 이는 클라이언트와 서버가 항상 연결된 상태를 유지하지 않는다는 것을 의미합니다.

  • 클라이언트로부터 요청을 받은 서버는 그에 대한 응답을 한 번 보내고 나면 연결을 종료합니다.

무상태성(Stateless)

  • 무상태성은 서버가 클라이언트의 이전 요청이나 상태에 대한 정보를 저장하지 않는다는 것을 의미합니다.

  • 클라이언트가 요청을 보낼 때마다 각 요청은 서로 독립적으로 취급됩니다.

장점

  • 비연결성은 서버의 리소스를 효율적으로 활용할 수 있게 해주며, 서버의 처리량 또한 향상시킵니다.

  • 무상태성은 서버의 부하를 줄이고, 각 요청을 독립적으로 처리할 수 있게 함으로써 더 높은 확장성을 제공합니다.

비연결성과 무상태성은 다음과 같은 장점이 존재하지만 이러한 특성 때문에, HTTP는 각 요청과 응답을 독립적으로 처리하고 연결을 끊어버리기 때문에, 클라이언트에 대한 이전 상태 정보나 현재 통신 상태를 저장하지 않습니다.

이로 인해 서버는 클라이언트를 식별할 수 없는 문제가 발생하며, 이는 로그인과 같은 상태를 유지해야 하는 작업에서 문제가 될 수 있습니다. 이런 문제를 해결하기 위해 다음과 같은 HTTP 인증과 인가 과정이 도입되었습니다.


쿠키는 웹사이트를 방문할 때, 해당 웹사이트의 서버를 통해 클라이언트 브라우저에 저장되는 작은 정보 파일입니다.

인증 과정

  1. 클라이언트 로그인 요청이 들어오면,서버는 클라이언트의 로그인 요청에 대한 응답으로, 클라이언트가 저장하려는 정보를 응답 헤더의 Set-Cookie(Key-Value 형식의 문자열)에 담아 전송합니다.

  2. 클라이언트는 요청을 보낼 때, 저장된 쿠키를 요청 헤더의 Cookie에 담아 서버에 전송합니다.

  3. 서버는 이렇게 전송된 쿠키를 기반으로 해당 요청을 보낸 클라이언트를 식별합니다.

단점

  • 보안 취약성: 쿠키는 요청 시에 값을 그대로 보내기 때문에, 중간에 가로채거나 조작될 가능성이 있습니다. 이로 인해 보안에 취약한 측면이 있습니다.

  • 용량 제한: 쿠키에 저장할 수 있는 데이터는 제한적이며, 큰 양의 정보를 담기 어렵습니다.

  • 브라우저 간 호환성: 각 브라우저는 쿠키를 다르게 처리하고 저장하는 방식을 가지고 있어, 쿠키를 다루는 방식이 브라우저 간에 다를 수 있습니다. 이로 인해 브라우저 간에 쿠키 정보를 공유하기 어렵습니다.

  • 네트워크 부하: 쿠키의 크기가 커지면 네트워크 부하가 증가할 수 있으며, 특히 많은 쿠키를 사용하거나 큰 쿠키를 전송할 때 이러한 부하가 더 심해질 수 있습니다.
    쿠키를 사용할 때는 보안과 개인정보 보호에 신중함이 필요하며, 필요한 정보만을 저장하고 적절한 보안 조치를 취해야 합니다.


3. Session

쿠키를 사용하여 클라이언트의 로그인 상태를 유지하는 것은 편리하지만, 위에서 언급했던 바와 같이 쿠키를 사용할 경우 가장 큰 단점은 유출 및 조작될 위험이 있으며, 개인정보를 HTTP로 전송하는 것은 보안상 위험하다는 것입니다.

세션은 비밀번호 등 클라이언트의 인증 정보를 쿠키 대신 서버 측에 안전하게 저장하고 관리합니다.

인증 과정

  1. 클라이언트 로그인 요청이 들어오면, 서버는 검증 후 클라이언트의 로그인 요청에 대한 응답으로 인증 정보를 서버에 저장합니다.

  2. 클라이언트를 식별하기 위한 JSESSIONID와 같은 세션 ID를 쿠키에 담아 전송합니다.

  3. 클라이언트는 요청을 보낼 때마다, JSESSIONID 쿠키를 함께 전송합니다.

  4. 서버는 JSESSIONID의 유효성을 검사하여 클라이언트를 식별합니다.

장점

  • 세션을 사용하면 클라이언트의 개인정보는 쿠키에 직접 노출되지 않기 때문에 쿠키와 비교하였을 때 상대적으로 안전합니다.

  • 각 사용자마다 고유한 세션 ID가 부여되므로, 요청이 들어올 때마다 회원 정보를 다시 확인할 필요가 없어 효율적입니다.

단점

  • 해커가 세션 ID를 중간에서 탈취하여 클라이언트를 위장하는 공격은 여전히 가능합니다.

  • 세션을 서버 측에서 관리하므로 요청이 많아지면 서버에 부하가 발생할 수 있습니다.


4. JWT

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

JWT 구조

JWT는 세 가지 문자열이 점(.)으로 구분되는 조합으로, 실제로 디코딩된 JWT는 아래와 같은 구조를 가지고 있습니다.

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

Headeralg와 typ을 갖고 있습니다.

alg는 정보를 암호화할 해싱 알고리즘을, typ토큰의 타입을 지정한다.

Payload

{
    "sub": "1234567890",
    "name": "John Doe",
    "iat": 1516230922
}

Payload는 토큰에 담을 정보를 지니고 있습니다.

주로 클라이언트의 고유 ID 값 및 유효 기간 등이 포함되는 영역입니다. key-value 형식으로 이루어진 한 쌍의 정보를 Claim이라고 칭합니다.

Signature

HMACSHA256 (
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    secret_key
)

Signature인코딩된 Header와 Payload를 더한 뒤 비밀키로 해싱하여 생성합니다.

Header와 Payload는 단순히 인코딩된 값이기 때문에 제 3자가 복호화 및 조작할 수 있지만, Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화할 수 없습니다.

따라서 Signature는 토큰의 위변조 여부를 확인하는데 사용됩니다.

인증 과정

  1. 클라이언트 로그인 요청이 들어오면, 서버는 검증 후 클라이언트 고유 ID 등의 정보를 Payload에 담습니다.

  2. 암호화할 비밀키를 사용해 Access Token을 발급합니다.

  3. 클라이언트는 전달받은 토큰을 저장해두고, 서버에 요청할 때 마다 토큰을 요청 헤더에 포함시켜 함께 전달합니다.

  4. 서버는 토큰의 Signature를 비밀키로 복호화한 다음, 위변조 여부 및 유효 기간 등을 확인합니다.

  5. 유효한 토큰이라면 요청에 응답합니다.

장점

  • Header와 Payload를 가지고 Signature를 생성하므로 데이터 위변조를 막을 수 있습니다.

  • 인증 정보에 대한 별도의 저장소가 필요 없습니다.

  • JWT는 토큰에 대한 기본 정보와 전달할 정보 및 토큰이 검증 됐음을 증명하는 서명 등 필요한 모든 정보를 자체적으로 지니고 있습니다.

  • 클라이언트의 인증 정보를 저장하는 세션과 다르게, 서버는 무상태가 됩니다.

  • 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능합니다.

  • 모바일 어플리케이션 환경에서도 잘 동작합니다.

단점

  • 쿠키, 세션과 다르게 JWT는 토큰의 길이가 길어, 인증 요청이 많을수록 네트워크 부하가 심해집니다.

  • Payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보는 담을 수 없습니다.

  • 토큰을 탈취당하면 대처하기 어렵다. 토큰은 한 번 발급되면 유효기간이 만료될 때까지 계속 사용이 가능합니다.

  • 쿠키/세션 기반 인증은 서버 단에서 쉽게 삭제할 수 있는 반면에 JWT의 경우 특정 사용자의 접속을 강제로 만료하기 어렵습니다.

Access Token이 탈취되었을 경우, 적절한 대응 방안이 필요합니다.

이런 상황을 해결하기 위한 방법은 Access Token의 유효 기간을 짧게 설정하고, Refresh Token을 사용하는 것입니다. 이렇게 하면, Access Token이 탈취당한 경우에도 그 토큰의 유효 기간이 짧기 때문에 공격자가 그 토큰을 이용한 피해를 상대적으로 줄일 수 있습니다.


5. Refresh Token

Refresh Token은 사용자가 애플리케이션에 로그인 상태를 유지하기 위해 사용하는 토큰입니다. Access Token의 유효기간이 끝나거나 만료된 경우, 새로운 액세스 토큰을 발급받기 위해 사용됩니다.

인증 과정, 재발급 과정

인증 과정

  1. 클라이언트 로그인 요청이 들어오고, 인증이 성공하면 서버는 Access Token과 Refresh Token을 발급합니다.
  2. Access Token은 사용자에게 전달되고, Refresh Token은 서버에 저장됩니다.
  3. 클라이언트는 Access Token을 안전한 저장소에 보관하고, API 요청을 보낼 때 Access Token을 헤더에 실어서 보냅니다.
  4. 서버는 Access Token의 유효성을 확인하고, 만료 여부를 확인합니다.
  5. Access Token이 유효하면 클라이언트에게 요청한 데이터를 반환합니다.

재발급 과정

  1. 사용자는 만료된 Access Token을 헤더에 실어 API 요청을 보냅니다.

  2. 서버는 Access Token의 만료를 확인하고, Access Token의 Payload를 통해 유효기간 여부를 판단합니다.

  3. Access Token이 만료되었을 경우, 서버로 Access Token을 재발급 요청합니다.

  4. 클라이언트는 Refresh Token과 함께 새로운 Access Token을 서버에 보냅니다.

  5. 서버는 받은 Access Token의 유효성을 확인하고, Refresh Token을 클라이언트 DB에 저장된 Refresh Token과 비교합니다.

  6. 유효하고 동일한 토큰인 경우, 새로운 Access Token을 클라이언트게 전달합니다.

  7. 클라이언트는 새로운 Access Token을 헤더에 실어 API 요청을 보냅니다.

profile
정신 🍒 !

0개의 댓글