You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

44 lines
1.2 KiB
Python

# backend/app/auth/tokens.py — 세션 id 서명/검증 + API 토큰 해시 (stdlib hmac, 의존성 없음)
import base64
import hashlib
import hmac
import secrets
from ..config import get_settings
def _key() -> bytes:
return get_settings().session_secret.encode("utf-8")
def new_session_id() -> str:
return secrets.token_hex(32) # 256-bit
def new_api_token() -> str:
return "ari_" + secrets.token_urlsafe(32)
def hash_token(token: str) -> str:
return hashlib.sha256(token.encode("utf-8")).hexdigest()
def sign_session_id(sid: str) -> str:
"""sid.<base64url(hmac)> — 쿠키에 들어가는 서명된 세션 id."""
mac = hmac.new(_key(), sid.encode("utf-8"), hashlib.sha256).digest()
return f"{sid}.{base64.urlsafe_b64encode(mac).decode().rstrip('=')}"
def unsign_session_id(signed: str) -> str | None:
"""서명 검증 후 sid 반환. 변조/형식 오류면 None."""
try:
sid, sig = signed.rsplit(".", 1)
except ValueError:
return None
expected = (
base64.urlsafe_b64encode(hmac.new(_key(), sid.encode("utf-8"), hashlib.sha256).digest())
.decode()
.rstrip("=")
)
return sid if hmac.compare_digest(sig, expected) else None