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
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
|