로그인 기능 설계(토큰방식) - ttasjwi/board-system GitHub Wiki
개요
- 사용자가 우리 서비스를 이용하기 위해서는 매 요청마다 인증이 필요하다.
- 인증을 위해서는 인증을 위한 자격증명을 사용자가 매 요청마다 전달해야하는데, 토큰 방식(JWT)를 사용하여 구현하기로 한다.
토큰 vs 세션
- 세션
- 사용자가 로그인을 하면, 세션ID/사용자 인증 정보를 생성한다. (주로 Redis)
- 인증 정보는 데이터베이스에 일정 시간동안 유효하게 저장되는데 이를 '세션'이라고 한다.
- 사용자에게 '세션Id' 를 발급하고(주로 쿠키를 통해), 사용자는 서비스를 이용할때마다 '세션Id'를 전달한다.
- 서비스에서는 '세션Id'를 통해 세션을 조회하고 현재 요청 사용자가 누구인지 확인하고 애플리케이션 로직에 활용한다. (인증)
-
토큰
- 사용자가 로그인하면 액세스토큰/리프레시 토큰을 생성한다.
- 액세스 토큰에는 사용자에 관한 정보가 포함되어지며, 보안상의 목적상 유효기간은 짧다.
- 리프레시 토큰은 유효시간이 길다. 액세스토큰이 만료될때 리프레시토큰을 전달하면, 액세스토큰을 재갱신한다. (액세스토큰의 짧은 유효기간 보완, 보안 강화)
- 사용자에게 액세스토큰, 리프레시토큰을 발급하고, 사용자는 서비스를 이용할 때마다 액세스토큰을 전달한다.
- 서비스에서는 액세스토큰을 통해 사용자 정보를 확인하고 애플리케이션 로직에 활용한다.
- 사용자가 로그인하면 액세스토큰/리프레시 토큰을 생성한다.
-
둘의 큰 차이점
- 세션은 사용자 인증 정보를 서비스에서 저장하여 관리한다.
- 사용자 실시간 정보를 데이터베이스에서 관리하고, 현재 인증상태를 실시간으로 서버에서 통제할 수 있는 장점이 있다.
- 다만 매번 데이터베이스를 통해 인증 정보를 조회해야하므로, 데이터베이스 부하가 증가하는 문제가 있다.
- 토큰은 사용자 인증 정보를 사용자가 서비스에 요청할 때마다 지참한다.
- 액세스 토큰을 파싱하여 사용자 인증 정보를 획득하므로 데이터베이스 조회 과정이 없다. (다만, 리프레시 토큰의 보안강화를 목적으로 리프레시토큰 통제는 데이터베이스를 활용하는 것이 현실적인 선택이다.)
- 액세스토큰의 유효기간동안 사용자 상태가 변경되거나, 회원의 탈퇴 등이 이루어질 경우 실제 저장된 사용자 정보와 토큰의 사용자 정보가 불일치할 수 있는 위험이 있다.
- 세션은 사용자 인증 정보를 서비스에서 저장하여 관리한다.
-
우리 서비스에서는
- 토큰 방식을 사용하기로 한다.
- 매번 사용자 인증 정보를 데이터베이스를 통해 획득하지 않아도 되는 장점이 크다.
- 서버에서의 실시간 정보와 사용자 현재 상태가 불일치할 수 있지만, 액세스토큰 유효시간을 30분 정도로 잡으면 큰 지장이 없을 것 같다.
JWT
- JSON Web Token
- JSON 데이터를 서명으로 암호화하여 웹 클라이언트 - 서버 간 데이터를 교환할 수 있게 한 기술
xxx.yyy.zzz
- JWT는 HEADER(xxx부분), PAYLOAD(yyy부분), SIGNATURE(zzz부분) 세 개의 부분으로 나뉜다.
- HEADER : 이 토큰이 어떤 토큰이고(typ), 어떤 알고리즘으로 서명됐는 지(alg)를 나타냄
- PAYLOAD : 토큰이 담은 데이터가 무엇인지 말하는 주장들(JWT Claim Set)을 묶어둔 부분
- SIGNATURE : HEADER(base64).PAYLOAD(base64) 를 alg 에 기술한 알고리즘으로 암호화한 결과물
- HEADER, PAYLOAD 만 놓고보면 누구든지 조작할 수 있기 때문에 신빙성이 없지만 SIGNATURE 부분이 잘 구성되어 있는지 확인할 수 있으면 토큰을 입증할 수 있다.
- 우리 서비스에서는 JWT 인코딩에 RSA 비대칭키 방식 암호화를 적용하여, 암호화했다.
액세스토큰, 리프레시 토큰
- 액세스토큰 : 사용자 인증/인가에 사용하는 토큰
- 리프레시 토큰 : 액세스토큰을 연장하기 위한 토큰(만료시간에 임박했을 경우 자기 자신도 갱신하는데 사용)