From 1230961c546e68eedfa22b8e9684e6ca42d23611 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 13 Sep 2026 11:32:22 +0900 Subject: [PATCH] =?UTF-8?q?chore(auth):=20=EA=B0=9C=EB=B0=9C=20=EB=8B=A8?= =?UTF-8?q?=EA=B3=84=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EC=83=9D=EB=9E=B5=20=EC=8A=A4=EC=9C=84=EC=B9=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 개발 중 로그인마다 인증 코드를 기다리던 것을 끄는 스위치. AUTH_OTP_DISABLED 가 true 이고 ENVIRONMENT 가 development 일 때만 듣는다 — 운영에서는 켜져 있어도 무시된다. - 로그인: 새 브라우저·주기 재인증 둘 다 코드 없이 통과, 생략마다 경고 로그 - 회원가입: 흐름은 그대로 두고 인증 코드를 서버 로그에 기록 - .env 에 AUTH_OTP_DISABLED=True (배포 전 False 로 되돌릴 것) Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TJC56e4osweKJ4vafm9ReM --- .env | 4 ++++ A06_Login/A06_Login_Router.py | 24 ++++++++++++++++++------ A07_Register/A07_Register_Router.py | 8 ++++++++ config/config_system.py | 7 +++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.env b/.env index 6b26492a..6749a85b 100644 --- a/.env +++ b/.env @@ -75,3 +75,7 @@ VWORLD_SESSION_COOKIE= # True면 대시보드 삭제 버튼이 DB 행과 storage/.../{프로젝트ID}/ 폴더를 실제로 지운다. # 배포 전 반드시 False로 되돌릴 것. PROJECT_DELETE_HARD_ENABLED=True + +# 개발 단계에서 로그인 이메일 인증(OTP)을 건너뛴다 (2026-09-13 사용자 지시). +# ENVIRONMENT=development 일 때만 듣는다. 배포 전 반드시 False 로 되돌릴 것. +AUTH_OTP_DISABLED=True diff --git a/A06_Login/A06_Login_Router.py b/A06_Login/A06_Login_Router.py index b653ead5..e60f62f4 100644 --- a/A06_Login/A06_Login_Router.py +++ b/A06_Login/A06_Login_Router.py @@ -1,5 +1,6 @@ """로그인, 재인증, 세션 및 비밀번호 API.""" +import logging from datetime import datetime, timedelta from fastapi import APIRouter, Depends, HTTPException, Request @@ -34,10 +35,12 @@ from common_util.common_util_auth_repository import ( ) from common_util.common_util_email import send_email_background from common_util.common_util_email_templates import otp_email, security_alert_email -from config.config_system import ADMIN_EMAIL, EMAIL_REVERIFY_DAYS +from config.config_system import ADMIN_EMAIL, AUTH_OTP_DISABLED, EMAIL_REVERIFY_DAYS from .A06_Login_Schema import LoginRequest, OtpVerifyRequest, PasswordChangeRequest +logger = logging.getLogger(__name__) + router = APIRouter(prefix="/api/auth", tags=["Authentication"]) @@ -85,11 +88,20 @@ async def request_login(payload: LoginRequest, request: Request): ) new_browser = not trusted_device if periodic_reverify or new_browser: - await _send_otp(user, "LOGIN", "로그인") - return { - "status": "otp_required", - "reason": "PERIODIC" if periodic_reverify else "NEW_BROWSER", - } + # 개발 단계에서는 메일 인증을 건너뛴다 (2026-09-13 사용자 지시). + # 이 갈래는 ENVIRONMENT=development + AUTH_OTP_DISABLED=true 에서만 열린다. + if AUTH_OTP_DISABLED: + logger.warning( + "[auth] 개발용 OTP 생략 — %s (%s)", + email, + "PERIODIC" if periodic_reverify else "NEW_BROWSER", + ) + else: + await _send_otp(user, "LOGIN", "로그인") + return { + "status": "otp_required", + "reason": "PERIODIC" if periodic_reverify else "NEW_BROWSER", + } return await _finish_login(user, agent, device_token_hash) diff --git a/A07_Register/A07_Register_Router.py b/A07_Register/A07_Register_Router.py index ca2d5b7b..51e49b61 100644 --- a/A07_Register/A07_Register_Router.py +++ b/A07_Register/A07_Register_Router.py @@ -1,5 +1,6 @@ """회원가입, 이메일 인증 및 회사 검색 API.""" +import logging from datetime import datetime from fastapi import APIRouter, HTTPException, Query, Request @@ -27,9 +28,12 @@ from common_util.common_util_auth_repository import ( ) from common_util.common_util_email import send_email_background from common_util.common_util_email_templates import otp_email +from config.config_system import AUTH_OTP_DISABLED from .A07_Register_Schema import RegisterRequest, RegisterVerifyRequest +logger = logging.getLogger(__name__) + router = APIRouter(prefix="/api/auth", tags=["Authentication"]) @@ -60,6 +64,10 @@ async def request_registration(payload: RegisterRequest): await replace_otp(user_id, "REGISTER", hash_password(code)) subject, html = otp_email(code, "회원가입") send_email_background(email, subject, html) + # 개발 단계에서는 메일을 못 받아도 가입을 이어갈 수 있게 코드를 로그에 찍는다 + # (2026-09-13 사용자 지시). ENVIRONMENT=development + AUTH_OTP_DISABLED=true 에서만. + if AUTH_OTP_DISABLED: + logger.warning("[auth] 개발용 가입 인증 코드 — %s : %s", email, code) return {"status": "success", "message": "인증 코드를 발송했습니다."} diff --git a/config/config_system.py b/config/config_system.py index 4a60494d..98ef486f 100644 --- a/config/config_system.py +++ b/config/config_system.py @@ -274,3 +274,10 @@ CORS_ORIGINS = os.getenv("CORS_ORIGINS", "http://localhost:5173,http://localhost # 9. 환경 정보 # ───────────────────────────────────────────────────────────────────────── ENVIRONMENT = os.getenv("ENVIRONMENT", "development") # development, staging, production + +# 개발 단계에서 로그인 이메일 인증(OTP)을 건너뛴다 (2026-09-13 사용자 지시). +# ⚠ 운영에서는 절대 켜지 않는다 — ENVIRONMENT 가 development 일 때만 듣는다. +# 가입 인증 코드는 건너뛰지 않고 서버 로그(tmp/server.log)에 찍어 메일 없이 진행한다. +AUTH_OTP_DISABLED = ( + os.getenv("AUTH_OTP_DISABLED", "False").lower() == "true" and ENVIRONMENT == "development" +)