diff --git a/app/api/auth.py b/app/api/auth.py index 4d8edb0..811f3e8 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -16,6 +16,7 @@ from core.auth import ( REFRESH_TOKEN_EXPIRE_DAYS, create_access_token, create_refresh_token, + create_voice_memo_bot_token, decode_token, get_current_user, hash_password, @@ -117,6 +118,11 @@ async def login( user.last_login_at = datetime.now(timezone.utc) await session.commit() + # Voice Memo PoC v1 — bot 계정 한정 long-expiry token (env gate). 일반 사용자 흐름 영향 0. + bot_token = create_voice_memo_bot_token(user.username) + if bot_token is not None: + return AccessTokenResponse(access_token=bot_token) + # refresh token → HttpOnly cookie _set_refresh_cookie(response, create_refresh_token(user.username)) diff --git a/app/core/auth.py b/app/core/auth.py index 80a8a95..de34b2c 100644 --- a/app/core/auth.py +++ b/app/core/auth.py @@ -1,5 +1,6 @@ """JWT + TOTP 2FA 인증""" +import os from datetime import datetime, timedelta, timezone from typing import Annotated @@ -37,6 +38,18 @@ def create_access_token(subject: str, expires_minutes: int | None = None) -> str return jwt.encode(payload, settings.jwt_secret, algorithm=ALGORITHM) +def create_voice_memo_bot_token(username: str) -> str | None: + # Voice Memo PoC v1 — bot 계정 한정 long-expiry access token (env gate + username hard-match). + # 일반 사용자 호출 시 None 반환. 정식 service-account/api_keys 는 Phase 2. + if os.getenv("VOICE_MEMO_BOT_TOKEN_ENABLED", "false").lower() != "true": + return None + bot_username = os.getenv("VOICE_MEMO_BOT_USERNAME", "voice-memo-bot") + if username != bot_username: + return None + expire_days = int(os.getenv("VOICE_MEMO_BOT_TOKEN_EXPIRE_DAYS", "365")) + return create_access_token(username, expires_minutes=expire_days * 24 * 60) + + def create_refresh_token(subject: str) -> str: expire = datetime.now(timezone.utc) + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS) payload = {"sub": subject, "exp": expire, "type": "refresh"} diff --git a/docker-compose.yml b/docker-compose.yml index 1313a43..40612b1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -194,6 +194,11 @@ services: - STT_ENDPOINT=http://stt-service:3300 # KGS Code 등 외부 학습 자료 추가 스캔 경로 (host .env 에서 주입). 빈 값이면 비활성. - ADDITIONAL_WATCH_TARGETS=${ADDITIONAL_WATCH_TARGETS:-} + # Voice Memo PoC v1 — bot 계정 한정 long-expiry access token. default false → 일반 운영 영향 0. + # 활성화: host .env 에 VOICE_MEMO_BOT_TOKEN_ENABLED=true. plan: rosy-launching-otter.md + - VOICE_MEMO_BOT_TOKEN_ENABLED=${VOICE_MEMO_BOT_TOKEN_ENABLED:-false} + - VOICE_MEMO_BOT_USERNAME=${VOICE_MEMO_BOT_USERNAME:-voice-memo-bot} + - VOICE_MEMO_BOT_TOKEN_EXPIRE_DAYS=${VOICE_MEMO_BOT_TOKEN_EXPIRE_DAYS:-365} restart: unless-stopped frontend: