추석에는 역시 토큰과 세션 공부하기 (작성 중)

삼콩·2023년 10월 4일
post-thumbnail

추석동안 그동안 궁금했지만 각잡고 공부해보지 못했던 로그인 로직 쪽을 공부하며 토큰과 세션에 대해 공부한 내용을 간단히 정리했습니다. 해당 내용은 코드팩토리님의 강의를 참고했습니다 (。・-・) 💕⁾⁾

(세션과 토큰은 서버의 구현 방식에 따라 조금씩 차이가 있고 아래 내용은 가장 보편적으로 쓰이는 방식에 대해 기술해놓은 것입니다. 틀린 정보가 있다면 댓글 부탁드립니다!)

세션과 토큰의 차이는? 유저의 정보를 어디에 저장하느냐의 차이이다

세션

session: 유저의 정보를 서버의 데이터베이스에 저장하고 상태를 유지하는 도구입니다

특징

  • 클라이언트는 세션 ID를 통해 서버와 상호작용합니다. 이 세션 ID는 특수한 ID 값으로 구성되어있습니다
  • 세션은 서버에서 생성되고 클라에서 쿠키를 통해 세션의 ID가 저장됩니다
  • 클라에서 요청을 보낼 때 세션 ID를 같이 보내면 현재 요청을 보내는 사용자가 누구인지 서버에서 알 수가 있습니다

단점

  • session ID는 데이터베이스에 저장이 되기 때문에 요청이 있을 때 마다 매번!데이터베이스를 확인해야합니다
  • 데이터 베이스에 session을 저장해야하기 때문에 horizontal scaling*이 어렵다는 단점이 있습니다

서버의 스케일링 방식

horizontal scaling : 수평적으로 서버를 늘리는 것 트래픽을 분산시키기 위한 확장 방식 => 세션을 중복 저장해야하는 문제가 있습니다
vertical scaling : 하나의 서버의 스펙을 업그레이드 하는 것

장점

  • 서버에서 데이터가 저장되기 때문에 클라에 사용자 정보가 노출될 위험이 없다

session은 어떻게 생성해?

client에서 - id/pass를 전송합니다 -> api 서버로
api 서버에서 - 검증합니다
api 서버에서 - 검증 확인 후 세션을 생성하고 및 저장합니다 -> database에
api 서버에서 - 세션을 담은 쿠키를 전송합니다 -> client로

session은 어떻게 사용해?

client에서 - 쿠키를 전송합니다 -> api 서버로
api 서버에서 - 쿠키안에 세션이 제대로된것인지 검증합니다
api 서버가 -> 해당 세션을 검색합니다 -> db로
db가 -> 응답합니다 -> api 서버로

api 서버가 -> 데이터 요청(ex.장바구니 관련 정보 요청)을 합니다 -> db로
db가 -> 데이터 응답을 합니다 -> api 서버로
api 서버가 -> 클라가 요청한 데이터를 전송합니다 -> client로

토큰

token: 유저의 정보를 base64로 인코딩된 string값에 저장하는 도구

특징

  • header.payload.signature 형태로 구성되어있으며 base64로 인코딩되어있습니다
  • 서버에서 생성되고 클라에 저장됩니다
  • token id를 같이보내면 사용자가 누구인지 서버에서 알 수 있습니다

단점

  • 정보가 모두 토큰에 담겨있고 클라에서 토큰을 저장하기 때문에 정보 유출의 위험이 있습니다 (유출이 되어도 상관이 없는 값만 저장해야합니다, 서버에서 그렇게 만들어 줄 것임!)

장점

  • db에 저장되지 않고 signature값(서명, 서버에 비밀번호 값이 있다)을 이용해서 검증할 수 있기 때문에 검증될 때마다 db를 매번 들여다볼 필요가 없습니다!
  • db가 필요없기 때문에 horizontal scaling이 쉽습니다!

token은 어떻게 생성해?

client가 - id/pass를 전송합니다 -> api 서버로
api 서버가 - 검증합니다 (토큰을 api서버에서 발급하고 저장안함!)
api 서버가 - 토큰을 전송합니다 -> client로

token은 어떻게 사용해?

client가 - token을 전송(header에 담아 전송)합니다 -> api 서버로
api 서버가 - 검증합니다
api 서버가 - 데이터를 요청합니다 -> db로
db가 - 결과를 응답합니다 -> api 서버로
api 서버가 - 데이터를 전송합니다 -> client로

세션 vs 토큰의 차이 정리

유저의 정보를 어디에서 저장하고 있는가?
세션 : 서버(세션 값 자체는 아무 의미 없음)
토큰 : 클라이언트(토큰 안에 정보가 있다)

클라에서 서버로 보내는 정보는?
세션 : 쿠키
토큰 : 토큰

유저 정보 가져올 때 db 확인해야하나?
세션 : 필요
토큰 : 불필요(토큰의 payload에 들어있는 정보만 필요한 경우엔 확인)

클라에서 인증 정보를 읽을 수 있는가?
세션 : 불가능
토큰 : 가능

horizontal scaling이 쉬운가?
세션 : 어려움
토큰 : 쉬움

jwt는 뭐야?

jwt는 토큰의 특수한 형태 중 하나입니다. 거의 대부분 jwt를 사용하는데요, jwt는 json web token의 약자로, header, payload, signature로 이루어져있습니다. base64로 인코딩 되어있습니다.

  • header : toekn 종류, 암호화 알고리즘 등 토큰에 대한 정보가 들어있따
  • payload : 발행일, 만료일, 사용자 id 등 사용자 검증에 필요한 정보
  • signature : base64로 인코딩된 헤더와 페이로드를 알고리즘으로 싸인한 값
    이 있다. 이 값을 기반으로 토큰이 발급된 뒤로 조작되었는지 확인할 수 있습니다. 요기서 예시 jwt로 실제 값을 바꿔보면 이해가 쉽습니당.

리프레시 토큰과 액세스 토큰은 뭐야?

두 토큰 모두 jwt 기반으로, 액세스 토큰은 api 요청시 검증용 토큰으로 사용됩니다. 누구로 로그인을 했는지 인증이 필요한 api를 사용할 때 반드시 헤더에 넣어서 보내야하구요, 리프래시토큰은 액세스 토큰을 추가로 발급할 때 사용됩니다. 액세스 토큰을 새로고침하는 기능이 있기 때문에 리프래시토큰이라고 합니다.

리프레시 토큰이 왜 필요한데?

액세스 토큰은 유효기간이 짧고 리프래시 토큰은 유효기간이 길어요. 자주 노출되는 액세스 토큰은 유효기간을 짧게해서 토큰이 탈취돼도 해커가 오래 사용하지 못하도록 방지할 수 있습니다. 상대적으로 노출이 적은 리프래시 토큰의 경우 액세스 토큰을 새로 발급받을 때만 사용되기 때문에 탈취 가능성이 적기 때문에 보안을 위해 리프레시 토큰을 사용하는 것입니다. 사용자는 재로그인을 하지 않고도, 본인이 인지하지 못하는 사이에 액세스 토큰을 재발급, 계속해서 로그인 상태를 유지하게 됩니다.

어떤 앱들은 로그인하고나서 어느 기간이 지나고 나면 재로그인을 시킬 때가 있는데 이것은 리프래시 토큰의 주기가 다되어 새로 리프레시 토큰을 발급받아야 하기 때문입니다.

토큰 발급 과정

클라이언트에서 로그인시 id/pass를 전송 합니다(id:password 값을 base64로 인코딩 후, authorization헤더에 Basic $token 형태로 전송)-> api 서버
(실제 인증값엔 basic)로

api server 는 토큰을 검증합니다

api 서버는 - 토큰을 전송합니다(refresh + access) -> client로

리프래시 토큰 사용 과정

client - access token 재발급 요청을 합니다. authorization 헤더에 Bearer $refreshToken 형태로 전송합니다 -> api server로

api server는 - refreshToken을 검증하고 access token 재발급합니다.

api server는 - 토큰을 전송합니다 -> client로

access token 사용과정

client는 - authoriztion에 Bearer $accessToken를 전송합니다 -> api server로
api server는 - 토큰을 검증합니다
api server는 - 데이터를 요청합니다 -> db로
db는 - 응답합니다 -> api server로
api server는 - 데이터를 응답합니다 -> client로

일반적인 토큰 인증 로직

토큰이 만료되어있는지 알 수 없으니까 만료가 되었다면 인증 기본 플로우는 이렇게 진행됩니다

client가 - api를 요청합니다 -> api 서버로
api 서버가 -> access token을 검증합니다
api 서버가 - access token 기간 만료 응답 (401)을 보냅니다 -> client로
client가 - access token 재발급 url로 요청합니다(refresh 토큰을 쏨) -> api server로
api server가 - refresh 토큰을 검증합니다 (이때 만약 refresh도 만료가 됐다면 로그아웃시킴)
api 서버가 - 새로운 access token 발급해서 응답합니다 -> client로
client가 - 새로운 access token을 저장하고 새로운 access token 으로 재요청합니다 -> api server로
api server가 - 데이터 요청을 합니다 -> db로
db가 - 데이터 응답을 합니다 -> api server로
api server가 - 데이터 응답을 합니다 -> client로

참고 문서
https://tecoble.techcourse.co.kr/post/2021-10-20-refresh-token/

profile
프론트엔드 세계의 모략을 꾸미는 김삼콩입니다

0개의 댓글