✅ 인증(Authentication)과 인가(Authorization)
세션과 토큰에 대해 알아보기 이전에 인증과 인가가 무엇인지 부터 알아야할 필요가 있다. 인증과 인가는 시스템의 자원을 적절하고 유효한 사용자에게 전달하고 공개하는 방법이다.
✅ 인증 (Authentication)
인증은 쉽게 말해 로그인이다. 클라이언트가 자신이라고 주장하고 있는 사용자가 맞는지를 검증하는 과정이다. 내가 로그인 화면에서 emhaki와 패스워드를 입력해 제출하면 서버에서는 내가 emhaki 유저가 맞는지 확인한다.
✅ 인가 (Authorization)
인가는 인증 이후에 행해지는 작업으로, 인증된 사용자에 대한 자원에 대한 접근 확인 절차를 의미한다. 인증을 해서 로그인이 되었다면, 유저는 다양한 활동을 하게 될 것이다. 예를 들면, 글 작성, 조회, 수정, 삭제 등 일반적인 활동을 하게되는데 자신에 대한 활동은 인가가 되어있어도 다른 사람이 작성한 글을 삭제하거나 수정할 수는 없다. 이는 타인의 리소스에 대해서는 인가가 되어 있지 않기 때문이다.
✅ HTTP의 비상태성(Stateless)
우리가 사용하는 HTTP는 비상태성 특성을 가진다. 서버는 클라이언트의 상태를 저장하지 않으며, 바로 직전에 발생한 통신을 기억하지 못한다. 따라서 HTTP 단독으로는 요청한 클라이언트가 이전에 이미 인증과정을 거쳤는지 알 방법이 없다.
그렇다고 해서 글을 조회하거나 페이지를 넘길 때마다 사용자에게 로그인을 하라고 요청할 수 없기 때문에 이 문제를 해결하기 위해 세션 또는 토큰을 사용한다. 즉, 세션과 토큰은 인증 보다는 인가와 관련된 기술이라고 할 수 있다.
✅ 세션기반 인증
Session 기반인증을 위해 Session과 Cookie가 사용된다.
- 유저가 로그인을 하고 세션이 서버 메모리 상에 저장된다. 이 때 세션을 식별하기 위한 Session ID를 기준으로 정보를 저장된다.
- 브라우저에 쿠키로 Session ID가 저장된다.
- 쿠키에 정보가 담겨있기 때문에 브라우저는 해당 사이트에 대한 모든 Request에 Session ID를 쿠키에 담아 전송한다.
- 서버는 클라이언트가 보낸 Session ID와 서버 메모리로 관리하고 있는 Session ID를 비교하여 Verification을 수행한다.
세션 기반 인증 장단점
장점
- 세션 기반 인증 방식은 구현이 상당히 명확하다는 장점. 또한 실제 서버에서 로그인 상태 확인이 굉장히 유용하다.
- 상대적으로 안전. 서버측에서 관리하기 때문에 클라이언트 변조에 영향을 받거나 데이터의 손상 우려가 없다.
단점
- 유저들의 세션에 대한 정보를 서버 메모리에 들고 있게 된다는 부담이 있다.
- 서버 메모리에 세션 정보가 저장되기 때문에 Scale Out / Scale In 이 부담이 될 수 있으며, 결국에는 유저 상태에 무관하게 동작할 수 있도록 Data-Driven 아키텍처가 요구된다.
- 멀티 디바이스 환경에서 로그인 시 신겨써줘야할 부분들이 생긴다.
✅ 토큰 기반 인증
Token 기반 인증의 방법으로 많은 웹 서버들이 JWT (JSON Web Token)을 사용한다.
Token 기반 인증 방식과 Session 기반 인증 방식의 가장 큰 차이점은 유저의 정보가 서버에 저장되지 않는다는 점이다.
- 유저가 로그인을 하고 서버에 세션을 이용해서 정보를 기록하는대신, Token을 발급한다.
- 클라이언트는 발급된 Token을 저장한다. (일반적으로 local Storage에 저장)
- 클라이언트는 요청 시 저장된 Token을 Header에 포함시켜 보낸다.
- 서버는 매 요청시 클라이언트로부터 전달받은 Header의 Token 정보를 Verification 한 뒤, 해당 유저에 권한을 인가한다.
Session 기반 인증은 서버가 서버측에 정보를 기록하는 반면, Token 기반 인증은 Token에 대한 Verification만 수행할 뿐 저장은 클라이언트에서 수행한다.
토큰 기반 인증 장단점
장점
- 클라이언트에 저장되기 때문에 서버의 메모리에 부담이 되지 않으며 Scale에 있어 대비책을 고려할 필요가 없다
- 멀티 디바이스 환경에 대한 부담이 없다.
단점
- 상대적으로 손상의 위험이 크다.
- 결국 구현을 하다보면 서버측에 token blacklist를 관리하게 될 가능성이 있고 그렇게 되면 서버측 메모리의 소모가 발생하게 된다.
- Token은 일반적으로 Session ID보다 길다.
- XSS 공격에 취약할 수 있어 가능한 민감한 정보는 포함시키지 않을 필요가 있다.
✅ 토큰의 형식
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
header, payload, verify signature 세가지 데이터를 이어붙인 형태
1번: header
{
"alg": "HS256",
"typ": "JWT"
}
- header에는 typ값이 고정값으로 들어있음
- alg는 알고리즘의 약자로 3번 서명(verify signature) 값을 만드는데 사용될 알고리즘이 지정된다. HS256, HS384 등 여러 암호화 방식 중 하나를 지정할 수 있다.
2번 : payload
{
"sub": "1234567890",
"name": "haki Em",
"iat": 1516239022
}
- Base64로 디코딩해보면 JSON형식으로 여러 정보들이 들어있음
- 토큰을 누구에게 발급했는지, 언제까지 유효한지, 사용자의 닉네임 등을 서비스 측에서 원하는대로 담을 수 있음
- 이렇게 토큰에 담긴 사용자 정보 등의 데이터를 Claim이라고 함
3번: verify signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
- 1번 header와 2번 payload 그리고 서버에 감춰놓은 비밀 값 이 셋을 암호화 알고리즘에 넣고 돌리면 3번 verify signature(t서명) 값이 나온다.
2번 payload의 정보가 서버가 아닌 누군가에 의해 수정된다면 어떻게 될까? (ex: client -> admin)
암호화 알고리즘이 한 쪽 방향으로는 계산이 되어도 반대쪽으로는 안되기 때문에 서버만 알고있는 비밀 값을 찾아낼 방법이 없다. 토큰을 탈취하더라도 글자 하나만 바뀌어도 3번 값이 완전히 달라지기 때문에 2번 payload를 수정해서 유효한 3번 verify signature 값이 나오려면 서버에 숨긴 비밀키를 알고 있어야 하기때문에 조작할 수 없다.
참고
https://www.youtube.com/watch?v=1QiOXWEbqYQ
https://hudi.blog/session-based-auth-vs-token-based-auth/
JWT 관련 사이트
'Computer Science' 카테고리의 다른 글
디자인 패턴(Design Pattern)이란? (0) | 2023.01.08 |
---|---|
컴파일러란? (feat. 인터프리터) (0) | 2023.01.06 |
GPU(그래픽 처리 장치) 개념 및 CPU와의 차이점 (0) | 2023.01.05 |
IPv4와 IPv6 개념 및 차이점 (0) | 2023.01.05 |
도메인(domain) 가볍게 살펴보기 (1) | 2023.01.04 |