jwt토큰

박민주·2024년 3월 4일
0

스프링시큐리티

목록 보기
2/6

토큰은 인증 및 승인에서 굉장히 중요한 역할을 수행하고 있습니다. 토큰에 대해 알아보겠습니다.

로그인 후 애플리케이션 탭에서 localhost:4200임이 확인되면 두 개의 쿠키를 보실 수 있습니다.

첫번째는 JSESSIONID, 두번째는 XSRF-TOKEN 입니다. 해당 쿠키들은 무작위로 생성된 값이고, 이러한 값들을 토큰(Token)이라고 부릅니다.

첫 번째는 JSESSIONID로, 로그인 성공 시 생성되며 이후의 모든 요청에서 자격증명을 다시 입력할 필요 없이 해당 쿠키가 자동으로 첨부됩니다. 두 번째는 XSRF-TOKEN으로, CSRF 공격을 방지하기 위해 사용됩니다.

Jsession

JSESSIONID은 SpringSecurity에서 생성되는 기본 토큰으로, 세션 관리에 사용되며, 브라우저에 의해 쿠키로 저장되므로 엔드 유저 세션이 유효한 경우 쿠키가 악용될 가능성이 있습니다. 따라서 기업 규모의 애플리케이션을 개발할 때에는 JSESSIONID만으로는 충분하지 않을 수 있습니다.

두가지 이유에 의해서입니다

  1. 첫째 Jsession 토큰은 유저 데이터를 갖고 있지 않습니다
    해당 토큰은 무작위로 생성된 값임을 볼 수 있는데 이에 의해 토큰 속에 유저 데이터를 저장할 수 없습니다..

  2. 두번째는 해당 JSESSIONID는 브라우저 속 쿠키로 저장 되는데 해당 쿠키는 유저 세션과 엮이게 됩니다.
    그리고 유저가 브라우저를 닫지 않아 엔드 유저 세션이 아직 유효하다면 누군가 브라우저에 그저 쿠키로 저장된 이러한 토큰들을 악용할 가능성이 높습니다.

토큰이란?

토큰은 범용 고유 식별자 (UUID) 형식의 일반 문자열 또는 JWT 토큰의 한 종류일 수 있습니다.

JWT는 JSON Web Token을 의미합니다

해당 토큰들은 일반적으로 엔드 유저의 인증이 완료 되자마자로그인 작업 중 처음으로 생성됩니다.

토큰이 생성된 후로는 해당 토큰이 클라이언트 애플리케이션에 의해 보호된 자료를 접근할 때마다 백엔드 시스템으로 보낼 수 있도록 사용될 수 있습니다

클라이언트 애플리케이션으로 보내진 해당 토큰이 유효하다면 백엔드 서버는 올바른 반응으로 대응할 것입니다.

  1. 유저가 백엔드 애플리케이션에 본인의 ID와 비밀번호를 이용하여 로그인을 시도합니다.

  2. 해당 자격증명이 유효하다면 백엔드 애플리케이션 또는 승인 서버가 무작위값을 가진 토큰을 생성합니다. 토큰은 클라이언트에게 다시 전달 됩니다.

  3. 클라이언트가 /user/myAccount과 같이 보안된 API 중 하나를 접속할 때는 클라이언트 애플리케이션은 반드시 같은 토큰을 백엔드 서버로 보내야 합니다.

  4. 이번에는 백엔드 서버가 해당 토큰이 유효하면 올바른 반응을 보내야 합니다

토큰을 사용해야하는 이유

  • 토큰은 모든 요청에 대해 자격증명을 공유하지 않도록 도와줍니다. 네트워크를 통해서 자격증명을 자주 보내는 것은 보안상 위험하기 때문입니다.
  • 사용자 자격증명을 무효화 하지않고도 의심스러운 활동을 감지한다면 토큰을 무효화해서 해결할 수 있습니다.
  • 짧은 수명을 갖도록 생성될 수 있습니다.
  • 토큰을 사용하여 엔드 유저의 유저 정보 혹은 역할(role) 정보를 저장할 수 있습니다
    - JSESSIONID 토큰 안에서는 이러한 유연성이 없습니다.
  • 토큰을 재사용 할 수 있다는 점입니다. 여러 플랫폼과 도메인에서 실행되고 사용자 인증을 위해 동일한 토큰을 재사용하는 여러개의 별도 서버를 가질 수 있습니다.
    - 예를 들어 구글은 많은 내부 애플리케이션을 갖고 있습니다. 유저가 지메일에서 구글 지도로 혹은 지메일에서 구글 드라이브로 이동할 때 구글이 자격증명을 계속해서 요구한다면 유저 친화적이지 못할 것입니다. 따라서 내부적으로 지메일에서 구글 드라이브로 토큰이 보내질 것이고 해당 토큰은 구글 드라이브에 의해 이용되며 승인 서버가 토큰에 대해 허락한다면 올바른 대답을 가질 것입니다 따라서 여기서 토큰이 여러 곳에서 재사용 되는 것을 볼 수 있고 토큰이 SSO (싱글 사인 온)을 이루는 데에 있어 도움이 되는 것을 볼 수 있습니다.
  • 무상태(stateless)로 있을 수 있습니다. 토큰에는 사용자를 식별하는 모든 정보가 포함되어있으므로 세션상태가 필요하지 않습니다. 로드 밸런서를 사용하면 로그인한 서버에 바인딩되는 대신 사용자를 모든 서버에 전달할 수 있습니다.
    - 여기서 무상태란 클러스터 환경같은 사이트 애플리케이션의 여러 인스턴스가 있을 때에서 로그인 중에 요청이 1번 인스턴스로 가고 이후의 요청들은 1번 인스터스로만 가지 않아도 되는 것입니다 2번 인스턴스, 3번 인스턴스 혹은 4번 인스턴스와 같이 클러스터 속 그 어떤 인스턴스에게 갈 수 있습니다. 그리고 다른 유저들이 로그인된 유저에 대해 알 수 있는 것도 토큰 덕분입니다 그리고 해당 인스턴스들은 세션 속 엔드 유저에 대해 특별히 기억하지 않아도 됩니다.

JWT 토큰

JWT는 JSON Web Token의 약자입니다. JWT는 데이터를 JSON 형식으로 유지하기 때문입니다. 그리고 이들은 웹 요청에 사용 되는데 특히 UI 클라이언트에서 백엔드 애플리케이션과 통신할 때 사용되며

REST 서비스의 도움으로 JSON 형식으로 통신하기 위해 설계되었습니다.
JWT는 갖고 있는 특징들과 장점 덕분에 가장 많이 사용되고 가장 선호되는 토큰 종류입니다. 다른 토큰들과 같이 인증 및 권한 부여가 가능합니다

또한, JWT 토큰은 토큰 자체의 내부에서 유저와 관련된 데이터를 저장 및 공유 할 수 있도록 도와 줍니다.

이는 서버 쪽 세션 안에 유저에 대한 정보를 갖고 있어야 하는 번거로움을 줄여줍니다. 무언가를 기억해야할 필요가 없고 완전히 무상태(Stateless)일 수가 있습니다.

왜냐하면 JWT 토큰 자체에서 유저와 관련된 필요한 정보를 모두 갖고 있기 때문입니다.

JWT 토큰은 보통 세 부분으로 나눠지며 마침표 혹은 점으로 구분됩니다.

노란색으로 표시된 부분을 우리는 JWT 토큰의 Header (헤더) 부분이라고 합니다.

헤더와 마침표 사이에 초록색으로 표시된 부분은 토큰의 Payload (내용)
또는 바디라고 합니다

마지막으로 Signature (서명) 부분이 있습니다. 이는 선택사항입니다

  • JWT 헤더 안에는 토큰에 대한 정보인 메타데이터가 저장되어 있습니다.
    주로 '알고리즘이 무엇인지?', '토큰의 종류가 무엇인지?'등 해당 JWT 토큰을 생성하며 사용된 토큰의 형식은 어떤 것인지 등의 정보를 담고 있습니다. 따라서 헤더는 메타데이터 정보만을 포함하고 있습니다
  • JWT 토큰 속 모든 정보는 평문 형식으로 보내지지 않습니다. 정보를 클라이언트에게 직접 전송하는 대신 JWT 토큰이 추천하는 바는 메타데이터의 값을 Base64로 인코딩하는 것입니다.
  • 이는 바디 혹은 내용(payload)라고 합니다. 저장을 원하는 유저에 대한 모든 정보를 저장할 수 있습니다
    - 예시로 그의 이름, 이메일, 역할, 토큰이 발행될 때, 만료 시간이 언제인지, 토큰을 발행한 자가 누군지, 토큰을 서명한 자는 누군지 등이 있습니다

로그인 과정이 성공적으로 진행되면 백엔드 애플리케이션에서 JWT 토큰을 생성하고 해당 토큰이 최초로 생성된 것과 동일한 토큰이라면 후속 작업은 성공적으로 수행될 수 있습니다

하지만 최초로 생성된 것과 현재 수신하는 것 사이에 불일치되는 부분이 있다면 분명 백엔드 서버에서 에러가 나타날 것입니다

여기 JWT 토큰의 장점이 하나 더 있습니다. 백엔드 서버의 가장 기본적인 접근은 해당 JWT 토큰을 처음 생성될 때마다 데이터베이스 혹은 캐시 속에 저장하는 것입니다 그리고 클라이언트에서 특정 JWT 토큰을 사용하는 요청에서는 해당 JWT 토큰이 이미 데이터베이스나 캐시에 저장된 토큰과 동일한지를 확인할 것입니다.

하지만 JWT 토큰의 서명 덕분에 어디에도 저장할 필요가 없습니다. 백엔드 서버가 할 수 있는 것은 헤더와 바디 속 값이 있는 JWT 토큰을 생성할 때마다 토큰에 디지털 서명을 하여 나중에 누군가가 토큰을 조작하려고 하면 쉽게 감지할 수 있습니다.

profile
개발자 되고싶다..

0개의 댓글