사용자의 인증 방법은 대표적으로 세션 기반 인증과 토큰 기반 인증이 있다.
세션 기반 인증
웹 애플리케이션에서 전통적으로 가장 많이 사용된 인증 방식으로, 절차는 다음과 같다.
- 사용자 로그인 요청
사용자가 아이디와 비밀번호를 입력하여 로그인 요청을 보낸다.
- 서버에서 인증 수행
아이디와 비밀번호가 유효하면 인증에 성공한다.
인증에 성공하면, 서버는 고유한 세션 ID를 생성하고 사용자 정보를 세션 저장소에 저장한다.
이 세션 ID는 클라이언트 브라우저에 Set-Cookie
헤더로 전달된다.
- 요청마다 세션 확인
이후 클라이언트의 모든 요청은 쿠키를 통해 세션 ID를 함께 전송한다.
서버는 이 세션 ID로 세션 저장소에서 사용자 정보를 조회하고 인증 여부를 판단한다.
장점
세션 정보를 서버에 저장해놓기 때문에, 단일 사용자의 다중 로그인 컨트롤, 사용자 유효성 체크, 강제 로그아웃 기능 구현이 편리하다.
단점
scale-out 과정이 어렵다.
여러 서비스에서 세션 정보를 공유하기 위해서는 세션 클러스터가 반드시 필요하다. 세션 클러스터의 장애 또는 성능 병목이 서비스 전체에 큰 영향을 준다.
토큰 기반 인증
토큰 기반 인증의 과정은 다음과 같다.
1. 클라이언트가 아이디와 비밀번호를 서버에게 전달하면서 인증을 요청한다.
2. 서버는 아이디와 비밀번호를 확인하여 유효한 사용자인지 검증하고, 유효한 사용자면 토큰을 생성하여 응답한다
3. 클라이언트는 서버에서 준 토큰을 저장하고, 이후 인증이 필요한 요청을 전송할 때마다 토큰을 함께 전송한다.
4. 서버는 토큰이 유효한지 검증하고, 유효하면 클라이언트가 요청한 작업을 처리한다.
특징
- stateless
사용자의 인증 정보가 담겨 있는 토큰이 서버가 아닌 클라이언트에 저장된다.
- 따라서, Active User가 많은 서비스에서 유리하다.
- 하지만, 유효기간이 남아 있는 정상적인 토큰에 대해 강제적으로 만료 처리가 어렵다.
- 토큰 크기를 가능한 작게 유지해야한다. 토큰 자체가 항상 HTTP 요청에 포함되어야 하기 때문에 토큰이 커질수록 불리하다.
- 확장성
무상태성으로 인해 서버를 확장할 때 상태 관리를 신경쓰지않아도 된다.
- 무결성
토큰 방식을 HMAC(Hash-based Message AuthentiCation)기법이라고도 부른다.
토큰을 발급한 이후에, 토큰 정보를 변경할 수 없어 무결성이 보장된다.
JWT(JSON Web Token)
사용자의 인증 정보를 JSON 형태로 인코딩한 토큰이다.
구조
JWT = base64urlEncode(header) + "." + base64urlEncode(payload) + "." + base64urlEncode(signature)
- header에는 토큰의 타입(e.g. JWT)과 해싱 알고리즘(e.g. HS256)이 저장된다.
- 해싱 알고리즘은 HMAC, RSA 방식을 지원한다.
- payload에는 전달하고자하는 데이터를 저장한다. 키-값의 한 쌍으로 이루어진 클레임의 집합이다. 클레임의 종류에는 registered claim, public claim, private claim이 있다.
- registered claim 종류
- iss : token issuer
- sub : token subject
- aud : token audience
- exp : token expiration. NumericDate 형식(e.g. 148084914730).
- nbf : Not Before의 의미로 token의 활성 날짜를 의미한다. NumericDate 형식(e.g. 148084914730).
- lat : token issued at
- jti : JWT의 고유 식별자로서, 주로 일회용 토큰에 사용한다.
- 기타 registered ciam 종류는 사이트를 참고한다.
- payload는 암호화되지 않으므로 민감한 정보는 절대 포함하지 않아야 한다.
- signature는 토큰의 조작이나 변경 유무를 확인하는 용도로 사용된다. header encoding 값과 payload encoding 값을 합친 후에 서버에 저장된 비밀 키를 사용해 해시값을 생성한다. 해시 알고리즘은 헤더에 정의된 알고리즘을 사용한다.
- HMAC 알고리즘에서 비밀키는 최소한 signature 길이 만큼의 비트 수를 가져야한다.
HS512 알고리즘 -> 최소 64 byte의 비밀키
- 비밀키는 윈도우 기준으로 git bash에
openssl rand -base64 <32 혹은 64>
명령어를 입력하여 생성한다.
- Header, Payload, Signature 세 부분을 Base64 Url-Safe 방식으로 인코딩하고, dot(
.
)을 구분자로 결합한다.
https://jwt.io 서비스에서 JWT 토큰을 인코딩 및 디코딩할 수 있다.

특징
- self-contained : JWT는 자체적으로 모든 정보를 가지고 있다.
- 토큰에 대한 메타정보 (토큰 타입, 해싱 알고리즘), 사용자 정의 데이터,토큰 유효성 검증을 위한 데이터
- payload는 암호화되지 않으므로 민감한 정보는 절대 포함하지 않아야 한다.
- Base64 Url-Safe 방식을 사용하여, 인터넷 상에서 전송이 용이하다.
- 위변조 검증이 가능하다.
refersh token
보안이 취약하여 토큰이 노출되면, 서버는 토큰과 함께 들어온 요청이 토큰을 탈취한 사람의 요청인지 확인할 수 없다.
토큰의 유효기간을 짧게 설정한다고 해도, 사용자 입장에서 불편하다.
따라서 사용자를 인증하기 위한 엑세스 토큰과 별도로, 유효 기간이 짧은 엑세스 토큰을 재발급하기 위한 목적의 토큰인 리프레시 토큰을 함께 관리한다. 리프레시 토큰의 유효기간은 길게 설정한다.
자세한 과정은 다음과 같다.
1. 클라이언트가 아이디와 비밀번호를 서버에게 전달하면서 인증을 요청한다.
2. 서버는 아이디와 비밀번호를 확인하여 유효한 사용자인지 검증하고, 유효한 사용자면 엑세스 토큰과 리프레시 토큰을 생성하여 응답한다. 이때, 서버는 생성한 리프레시 토큰을 DB에 저장한다.
3. 클라이언트는 서버에서 받은 두 토큰을 저장하고, 이후 인증이 필요한 요청을 전송할 때마다 엑세스 토큰을 함께 전송한다.
4. 서버는 엑세스 토큰이 유효한지 검증하고, 유효하면 클라이언트가 요청한 작업을 처리한다.
5. 시간이 지나고 액세스 토큰이 만료된 뒤에 클라이언트는 인증이 필요한 요청을 전송한다. 이때, 엑세스 토큰을 함께 전송한다.
6. 서버는 엑세스 토큰이 유효한지 검증한다. 하지만 엑세스 토큰이 만료되어 유효하지 않기 때문에 토큰이 만료되었다는 에러를 클라이언트로 응답한다.
7. 클라이언트는 이 응답을 받고 저장해둔 리프레시 토큰과 함께 새로운 엑세스 토큰을 발급하는 요청을 전송한다.
8. 서버는 리프레시 토큰이 유효한지, DB에서 조회한 리프레시 토큰과 값이 같은지 확인한다. 유효하면 새로운 엑세스 토큰을 생성하여 응답한다.