auth-basic
1. 인증⚑
1.1. TL; DR⚑
- JWT (JSON Web Token)
- 클라이언트와 서버 간에 정보를 안전하게 전송하기 위한 토큰.
- 주로 사용자 인증에 사용됨.
- 토큰은 세 부분(헤더, 페이로드, 서명)으로 구성되며, 서명 부분을 통해 변조 여부를 확인할 수 있음.
- JWT 장점
- 확장성: 상태 비저장 방식으로 서버 확장에 유리.
- 자기 포함된 토큰: 추가적인 데이터베이스 조회 없이도 정보 확인.
- 다양한 클라이언트 지원: 웹, 모바일 등 여러 클라이언트에서 사용 가능.
- 상태 유지 없이 인증: 서버의 메모리 사용을 줄이고 효율적인 인증 시스템 구현.
- Session
- 서버 측에 저장되는 사용자 상태 정보.
- 클라이언트는 세션 ID를 쿠키로 저장하고 서버에 전송하여 상태를 유지함.
- 세션 데이터는 서버 메모리, 파일 시스템 또는 데이터베이스에 저장됨.
- 세션의 장점
- 보안성: 세션 데이터가 서버에만 저장.
- 세션 무효화 용이: 중앙에서 세션을 쉽게 무효화.
- 서버 제어: 모든 세션을 서버에서 관리 및 제어.
- Cookie
- 클라이언트 측(브라우저)에 저장되는 작은 데이터 조각.
- 주로 상태를 유지하기 위해 사용됨 (예: 세션 ID, 사용자 설정).
- HTTP 요청 시 자동으로 서버에 전송됨.
1.2. JWT (JSON Web Token)⚑
- https://datatracker.ietf.org/doc/html/rfc7519
- base64url 인코딩 되어있고, https://jwt.io/ 등 에서 JWT 디코딩 가능
- Token 구조
- Header: 토큰 유형 및 서명 알고리즘을 포함
- typ (type): 토큰 유형 (일반적으로 JWT)
- alg (algorithm): 서명 알고리즘 (HS256, RS256, ES256 등)
- Payload: 클레임(claim) 정보를 포함
- Registered claims: 토큰에 대한 정보를 제공하는 표준 클레임
- iss (issuer): 토큰 발급자
- sub (subject): 토큰의 주제 (주로 사용자 ID)
- aud (audience): 토큰 대상자
- exp (expiration time): 토큰 만료 시간
- iat (issued at): 토큰 발급 시간
- nbf (not before): 토큰 사용 시작 시간
- jti (JWT ID): 토큰 식별자
- Public claims: 공개 클레임은 충돌을 방지하기 위해 IANA JSON Web Token Registry에 등록
- Private claims: 서버와 클라이언트 간에 사용되는 클레임
- 사용자 ID, 사용자 권한, 사용자 설정 등
- Registered claims: 토큰에 대한 정보를 제공하는 표준 클레임
- Signature: 서명 알고리즘을 사용하여 헤더와 페이로드를 서명한 값
- Header: 토큰 유형 및 서명 알고리즘을 포함
1.2.1. Flow⚑
sequenceDiagram
participant User
participant Client
participant Server
User ->> Client: 사용자명과 비밀번호 입력
Client ->> Server: 로그인 요청 (사용자명, 비밀번호)
Server ->> Server: 자격 증명 확인
alt 자격 증명 유효
Server ->> Client: JWT 생성 및 반환
Client ->> User: 로그인 성공
User ->> Client: 인증된 요청 (JWT 포함)
Client ->> Server: 요청 (JWT 포함)
Server ->> Server: JWT 검증
alt JWT 유효
Server ->> Client: 요청 처리 및 응답
else JWT 유효하지 않음
Server ->> Client: 요청 거부 (401 Unauthorized)
end
else 자격 증명 무효
Server ->> Client: 로그인 실패 (401 Unauthorized)
end
1.2.2. JWT 검증 과정 (JWT Validation)⚑
- 요청 수신:
- 클라이언트는 서버에 요청을 보낼 때 JWT를 요청 헤더의 Authorization 필드에 포함시켜 보냅니다.
- 예시:
Authorization: Bearer <JWT>
- JWT 파싱:
- 서버는 요청에서 JWT를 추출합니다.
- JWT는 기본적으로 세 부분으로 나뉩니다: 헤더(header), 페이로드(payload), 서명(signature).
- 서명 검증:
- 서버는 JWT의 서명을 검증하여 토큰이 변조되지 않았는지 확인합니다.
- 서버는 JWT를 생성할 때 사용한 비밀 키를 사용하여 서명을 검증합니다.
- 서명 검증이 실패하면, 서버는 요청을 거부합니다.
- 페이로드 검토
- 서명 검증이 성공하면, 서버는 페이로드의 내용을 검토합니다.
- 페이로드에는 사용자 ID, 발행 시간, 만료 시간 등의 정보가 포함됩니다.
- 토큰 만료 확인
- 서버는 페이로드에 포함된 만료 시간(exp 클레임)을 확인합니다.
- 만료 시간이 현재 시간보다 이전이면, 서버는 요청을 거부합니다.
- 추가 검증 (옵션):
- 서버는 필요에 따라 추가 검증을 수행할 수 있습니다.
- 예를 들어, 사용자 권한을 확인하거나 특정 클레임의 유효성을 확인할 수 있습니다.
- 요청 처리:
- JWT가 유효하고 모든 검증을 통과하면, 서버는 요청을 처리합니다.
1.2.3. Signing Algorithm⚑
- https://auth0.com/docs/get-started/applications/signing-algorithms
-
대칭키 서명 (HMAC 알고리즘)
- 대칭키 서명은 하나의 비밀 키를 사용하여 JWT를 서명하고 검증합니다. 서버가 JWT를 생성할 때와 검증할 때 동일한 비밀 키를 사용
- 일반적으로 HMAC 알고리즘 (HS256, HS384, HS512 등)을 사용
- 키 관리가 간단하지만, 비밀 키가 노출되면 보안에 취약
-
비대칭키 서명 (RSA 또는 ECDSA 알고리즘)
- 비대칭키 서명은 공개 키와 개인 키 쌍을 사용합니다. 서버는 개인 키로 JWT를 서명하고, 공개 키로 검증합니다.
- 일반적으로 RSA (RS256, RS384, RS512) 또는 ECDSA (ES256, ES384, ES512) 알고리즘을 사용합니다.
- 개인 키로 서명하고 공개 키로 검증
- 공개 키가 노출되어도 안전하지만, 키 쌍을 관리해야 하는 복잡성
1.2.4. Refresh Token & Access Token⚑
- Access Token
- 짧은 유효 기간을 가지며, 주로 API 요청에 사용
- 만료 시간이 지나면, 클라이언트는 새로운 토큰을 요청
- Refresh Token
- 긴 유효 기간을 가지며, Access Token을 새로 발급하는 데 사용
- Access Token이 만료되면, Refresh Token을 사용하여 새로운 Access Token을 발급
sequenceDiagram
participant User
participant Browser
participant Server
User ->> Browser: 사용자명과 비밀번호 입력
Browser ->> Server: 로그인 요청 (사용자명, 비밀번호)
Server ->> Server: 자격 증명 확인
alt 자격 증명 유효
Server ->> Browser: 로그인 성공 (액세스 토큰, 재발급 토큰 발급)
Browser ->> User: 로그인 성공, 토큰 저장
User ->> Browser: 보호된 리소스 요청
Browser ->> Server: 보호된 리소스 요청 (액세스 토큰 포함)
Server ->> Server: 액세스 토큰 검증
alt 액세스 토큰 유효
Server ->> Browser: 보호된 리소스 데이터 전송
Browser ->> User: 보호된 리소스 표시
else 액세스 토큰 만료
Server ->> Browser: 인증 실패 메시지 (401 Unauthorized)
Browser ->> User: 인증 실패 메시지 표시
User ->> Browser: 새로운 액세스 토큰 요청
Browser ->> Server: 재발급 토큰을 사용한 액세스 토큰 재발급 요청
Server ->> Server: 재발급 토큰 검증
alt 재발급 토큰 유효
Server ->> Browser: 새로운 액세스 토큰 발급
Browser ->> User: 새로운 액세스 토큰 저장
User ->> Browser: 보호된 리소스 재요청
Browser ->> Server: 보호된 리소스 요청 (새로운 액세스 토큰 포함)
Server ->> Server: 새로운 액세스 토큰 검증
Server ->> Browser: 보호된 리소스 데이터 전송
Browser ->> User: 보호된 리소스 표시
else 재발급 토큰 무효
Server ->> Browser: 인증 실패 메시지 (403 Forbidden)
Browser ->> User: 재로그인 요청
end
end
else 자격 증명 무효
Server ->> Browser: 로그인 실패 메시지
Browser ->> User: 로그인 실패 메시지 표시
end
1.3. Cookie⚑
- https://datatracker.ietf.org/doc/html/rfc6265
- 각 쿠키는 단순한 이름-값 쌍
- 서버가 응답할 때 Set-Cookie: 헤더를 포함하여 쿠키를 정의
- 이후 브라우저가 동일한 서버에 연결할 때마다 Cookie: 헤더를 포함하여 이름과 값을 서버에 보내고, 서버는 이를 사용하여 관련된 요청을 연결
- 만료일 혹은 지속시간을 명시할 수 있고, 만료된 쿠키는 더 이상 보내지 않은.
- 추가적으로 특정 도메인 혹은 경로 제한을 설정할 수 있음
1.4. Session⚑
- https://datatracker.ietf.org/doc/html/rfc6265#section-8.4
- 세션 정보를 직접 쿠키에 저장하는 대신(이 경우 공격자가 노출시키거나 재사용할 수 있음), 서버는 일반적으로 쿠키에 난수 값(또는 "세션 식별자")을 저장합니다. 서버가 난수 값을 포함한 HTTP 요청을 받으면, 해당 난수 값을 키로 사용하여 쿠키와 관련된 상태 정보를 조회할 수 있습니다.
1.4.1. Session Management⚑
- 로그인 요청
- 사용자가 브라우저에서 사용자명과 비밀번호를 입력하고 서버에 로그인 요청을 보냅니다.
- 서버는 자격 증명을 확인합니다.
- 자격 증명 확인
- 자격 증명이 유효한 경우, 서버는 세션을 생성하고 세션 ID를 포함한 쿠키를 브라우저에 전송합니다.
- 자격 증명이 무효한 경우, 서버는 로그인 실패 메시지를 브라우저에 전송합니다.
- 보호된 페이지 요청
- 사용자가 보호된 페이지를 요청하면 브라우저는 서버에 세션 ID를 포함한 쿠키를 전송합니다. - 서버는 세션 ID를 검증하여 유효성을 확인합니다.
- 세션 검증
- 세션이 유효한 경우, 서버는 보호된 페이지 데이터를 브라우저에 전송합니다.
- 세션이 무효한 경우, 서버는 인증 실패 메시지를 브라우저에 전송합니다.
- 로그아웃
- 사용자가 로그아웃을 요청하면 브라우저는 서버에 로그아웃 요청을 보냅니다.
- 서버는 세션을 삭제하고 로그아웃 성공 메시지를 브라우저에 전송합니다.
sequenceDiagram
participant User
participant Browser
participant Server
User ->> Browser: 사용자명과 비밀번호 입력
Browser ->> Server: 로그인 요청 (사용자명, 비밀번호)
Server ->> Server: 자격 증명 확인
alt 자격 증명 유효
Server ->> Browser: 로그인 성공, 세션 ID 발급 (Set-Cookie: sessionId=)
Browser ->> User: 로그인 성공 메시지
User ->> Browser: 보호된 페이지 요청
Browser ->> Server: 보호된 페이지 요청 (쿠키: sessionId=)
Server ->> Server: 세션 ID 검증
alt 세션 유효
Server ->> Browser: 보호된 페이지 데이터 전송
Browser ->> User: 보호된 페이지 표시
else 세션 무효
Server ->> Browser: 인증 실패 메시지 (401 Unauthorized)
Browser ->> User: 인증 실패 메시지 표시
end
else 자격 증명 무효
Server ->> Browser: 로그인 실패 메시지
Browser ->> User: 로그인 실패 메시지 표시
end
User ->> Browser: 로그아웃 요청
Browser ->> Server: 로그아웃 요청 (쿠키: sessionId=)
Server ->> Server: 세션 삭제
Server ->> Browser: 로그아웃 성공 메시지
Browser ->> User: 로그아웃 성공 메시지 표시