JWT 토큰

황희윤·2023년 7월 30일

사용자 인증 확인 방법에는 두 가지가 있다.

세션 기반 인증

스프링 시큐리티에서 기본적으로 제공해주는 세션 기반 인증은 사용자마다 사용자의 정보를 담은 세션을 생성하고 저장해서 인증한다.

토큰 기반 인증

토큰은 서버에서 클라이언트를 구분하기 위한 유일한 값으로 서버가 토큰을 생성해서 클라이언트에게 제공하면 클라이언트는 이 토큰을 갖고 있다가 여러 요청을 이 토큰과 함께 신청한다. 서버는 다시 받은 토큰을 보고 유효한 사용자인지 검증한다.

토큰 기반 인증 과정

  1. 클라이언트가 아이디비밀번호를 서버에게 전달

  2. 서버는 아이디와 비밀번호를 확인해 사용자 검증. 유효한 사용자면 토큰생성해서 클라이언트에게 전달

  3. 클라이언트는 서버에게 준 토큰을 저장

  4. 클라이언트는 이후 인증이 필요한 API를 사용할 때 토큰을 서버로 함께 전달

  5. 서버는 받은 토큰을 유효한지 검증

  6. 토큰이 유효하면 클라이언트 요청 처리


토큰 기반 인증의 특징

1. 무상태성

  • 사용자의 인증 정보가 담겨 있는 토큰이 서버가 아닌 클라이언트에 있으므로 서버에 저장할 필요가 없다.

  • 그래서 서버 입장에서는 클라이언트의 인증 정보를 저장하거나 유지하지 않아도 되서 완전한 무상태(stateless)로 효율적인 검증이 가능하다.

2. 확장성

  • 서버를 확장할 때 상태 관리를 신경 쓸 필요가 없으니 서버 확장이 쉽다.

  • 세션 인증 기반은 각각 API에서 인증을 해야 되는 것과 달리 토큰 기반 인증에서는 하나의 토큰으로 결제 서버와 주문 서버 등 다른 API에게 요청을 보낼 수 있다.

  • 페이스북 로그인, 구글 로그인 같이 토큰 기반 인증을 사용하는 다른 시스템에 접근해 로그인 방식을 확장할 수 있다.

3. 무결성

  • 토큰 방식은 HMAC(hash-based message authentication) 기법이라고도 부른다.

  • 토큰을 발급한 이후에는 토큰 정보를 변경하는 행위는 할 수 없기 때문에 토큰의 무결성이 보장된다.


JWT (JSON Web Token)

구조

1. 헤더 (header)

  • 토큰의 타입과 해싱 알고리즘을 지정하는 정보를 담는다
    {
     // JWT 토큰, HS256 해싱 알고리즘을 사용한다
     "typ": "JWT",
     "alg": "HS256"
    }

2. 내용 (payload)

  • 토큰과 관련된 정보를 담는다.

  • 내용의 한 덩어리를 클레임(claim)이라 부르며, 클레임은 키값의 한 쌍으로 이루어져 있다.

  • 클레임은 등록된 클레임, 공개 클레임, 비공개 클레임으로 나눠진다.

  • 등록된 클레임(registered claim)은 토큰에 대한 정보를 담는데 사용된다.

  • ex) 토큰 발급자, 만료 시간, 제목, 대상자 등

  • 공개 클레임(public claim)은 공개되어도 상관없는 클레임

  • 충돌을 방지할 수 있는 이름을 사용해야 되서, 보통 클레임 이름을 URI로 짓는다.

  • 비공개 클레임(private claim)은 공개 되면 안되는 클레임으로 클라이언트와 서버 간의 통신에 사용된다.

{
  "iss": "12321@gmail.com", // 등록된 클레임(토큰 발급자 issuer)
  "iat": 1622370878, // 등록된 클레임(토큰 발급 시간)
  "exp": 1622372678, // 등록된 클레임(토큰 만료 시간)
  "https://1234321.com/1234321": true, // 공개된 클레임(클레임 이름 URI)
  "email": "12321@gmail.com", // 비공개 클레임
  "hello": "안녕하세요!" // 비공개 클레임
}

3. 서명(signature)

  • 해당 토큰이 조작되었거나 변경되지 않았음을 확인하는 용도

  • 헤더의 인코딩 값과 내용의 인코딩 값을 합친 후에 주어진 비밀키를 사용해 해시값 생성


🔑 Access Token

사용자의 인증 혹은 자원에 대한 접근을 위해 사용되는 토큰

  • 사용자가 로그인에 성공하면, 서버는 해당 사용자에게 Access Token을 준다.

  • 발근된 Access Token은 클라이언트 측의 임시 저장소에 저장되어 있다가, 요청 시 헤더에 포함되어 서버에 전달한다.

  • 주로 유효기간이 짧다.

  • Access Token의 유효기간이 만료되면, 클라이언트는 새로운 Access Token을 서버에 요청한다.

Refresh Token

Access Token의 갱신과 세션 관리에 사용되는 토큰

  • Refresh Token은 사용자가 로그인에 성공하면 생성되어 서버에 저장된다.

  • 유효기간이 길며 주로 일주일에서 한 달 사이다.

  • Refresh token이 만료되면 다시 로그인해서 재인증 과정을 거친다.

리프레시 토큰 인증 과정

  1. 클라이언트가 서버에게 인증 요청

  2. 서버는 클라이언트에서 전달한 정보를 바탕으로 인증 정보가 유효한지 확인한 뒤, 액세스 토큰과 리프레시 토큰을 만들어 클라이언트에게 전달

  3. 서버에서 생성한 리프레시 토큰은 DB에도 저장

  4. 인증을 필요로 하는 API를 호출할 때 클라이언트에서 저장된 액세스 토큰과 함께 API를 요청

  5. 전달받은 액세스 토큰이 유효한지 서버에서 검사한 뒤에 유효하다면 클라이언트에서 요청한 내용을 처리

  6. 시간이 지나고 액세스 토큰이 만료된 뒤에 클라이언트에서 원하는 정보를 얻기 위해 서버에게 API 요청을 보냄

  7. 서버에서 액세스 토큰이 유효한지 검사. 만료된 토큰이 유효하지 않기 때문에 토큰이 만료되었다는 에러 전달

  8. 클라이언트에서는 저장해둔 리프레시 토큰과 함께 새로운 액세스 토큰을 발급하는 요청을 전송

  9. 서버에서는 전달받은 리프레시 토큰이 유효한지, DB에서 리프레시 토큰을 조회한 후 저장해둔 리프레시 토큰과 같은지 확인

  10. 만약 유효한 리프레시 토큰이라면 새로운 액세스 토큰을 생성한 뒤 클라이언트에게 전달

  11. 클라이언트는 새로 발급 받은 액세스 토큰으로 다시 요청


JWT 장점

쿠키세션 : 서버 단에 로그인한 모든 사용자의 세션을 DB나 캐시(cache)에 저장해놓고 쿠키로 넘어온 세션 ID로 사용자 데이터를 매번 조회해야 한다. 유저 수가 많을 때는 조회 속도가 오래 걸린다.

JWT : 토큰 자체에 사용자의 정보가 저장되어 있기 때문에 서버 입장에서 토큰을 확인만 해주면 된다. 쿠키를 사용하지 않아서 CORS 문제에서도 자유로워 진다.

JWT 한계

로그인된 모든 사용자의 아이디를 나열하거나 특정 사용자의 로그아웃을 하게끔 하는 것을 구현하려면 결국 서버 단에 사용자 세션을 저장해야 한다. 이렇게 되면 세션과 비슷해진다.

또한 JWT 토큰 안에는 사용자의 아이디가 담겨 있어서 꼭 필요하고 공개되어도 괜찮은 정보만 넣는 것이 좋다.

profile
HeeYun's programming study

0개의 댓글