From 9c967af9c12d94ea128c7acfd3c41b6e617cc397 Mon Sep 17 00:00:00 2001 From: "jihoon87.lee" Date: Thu, 5 Feb 2026 13:19:53 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EC=A7=81=ED=9B=84=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=99=84=EB=A3=8C=20=EC=B2=98=EB=A6=AC=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 app/auth/callback/route.ts - OAuth 콜백 처리 시 신규 사용자(생성 시간 1분 이내)를 감지하면 자동 로그인 세션을 종료하고 로그인 페이지로 리다이렉트하며 이메일 인증 완료 메시지를 전달하도록 로직 추가 - 일반 로그인은 기존처럼 코드 파라미터 제거 후 깔끔한 URL로 리다이렉트하도록 유지 features/auth/constants.ts - 이메일 인증 성공 메시지 상수 추가 - 일부 문자열 포맷팅 정리 --- app/auth/callback/route.ts | 27 ++++++++++++++++++++++++++- features/auth/constants.ts | 7 +++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts index 6fe38d4..7873e82 100644 --- a/app/auth/callback/route.ts +++ b/app/auth/callback/route.ts @@ -62,8 +62,33 @@ export async function GET(request: NextRequest) { if (!exchangeError) { // ---------------------------------------------------------------------- // 3-1. 교환 성공: 리다이렉트 처리 - // 코드 파라미터 등을 제거하고 깨끗한 URL로 이동합니다. + // code 교환으로 세션이 생성된 상태입니다. // ---------------------------------------------------------------------- + + const { + data: { user }, + } = await supabase.auth.getUser(); + + // 회원가입 직후 인증 여부 확인 (생성된 지 1분 이내) + // 별도의 type 파라미터 없이 데이터 기반으로 판단합니다. + const isNewUser = + user && + user.created_at && + new Date(user.created_at).getTime() > Date.now() - 60 * 1000; // 1분 이내 생성 + + // 회원가입 인증인 경우: + // 이메일 인증만 완료하고, 자동 로그인된 세션은 종료시킨 뒤 로그인 페이지로 보냅니다. + if (isNewUser) { + await supabase.auth.signOut(); + return NextResponse.redirect( + `${origin}${AUTH_ROUTES.LOGIN}?message=${encodeURIComponent( + AUTH_ERROR_MESSAGES.EMAIL_VERIFIED_SUCCESS, + )}`, + ); + } + + // 그 외 일반적인 로그인/인증인 경우: + // 코드 파라미터 등을 제거하고 깨끗한 URL로 이동합니다. const forwardedHost = request.headers.get("x-forwarded-host"); // 로드밸런서 지원 const isLocalEnv = process.env.NODE_ENV === "development"; diff --git a/features/auth/constants.ts b/features/auth/constants.ts index c60ee3a..b42a628 100644 --- a/features/auth/constants.ts +++ b/features/auth/constants.ts @@ -40,6 +40,7 @@ export const AUTH_ERROR_MESSAGES = { // === 인증 링크 === INVALID_AUTH_LINK: "인증 링크가 만료되었거나 유효하지 않습니다.", + EMAIL_VERIFIED_SUCCESS: "이메일 인증이 완료되었습니다. 로그인해 주세요.", // === 소셜 로그인 (OAuth) 관련 === OAUTH_ACCESS_DENIED: "로그인이 취소되었습니다.", @@ -106,8 +107,10 @@ export const AUTH_ERROR_CODE_MESSAGES = { mfa_verification_failed: "MFA 검증에 실패했습니다.", mfa_verification_rejected: "MFA 검증이 거부되었습니다.", mfa_verified_factor_exists: "이미 검증된 전화 MFA가 존재합니다.", - mfa_web_authn_enroll_not_enabled: "WebAuthn MFA 등록이 비활성화되어 있습니다.", - mfa_web_authn_verify_not_enabled: "WebAuthn MFA 검증이 비활성화되어 있습니다.", + mfa_web_authn_enroll_not_enabled: + "WebAuthn MFA 등록이 비활성화되어 있습니다.", + mfa_web_authn_verify_not_enabled: + "WebAuthn MFA 검증이 비활성화되어 있습니다.", no_authorization: "Authorization 헤더가 필요합니다.", not_admin: "관리자 권한이 없습니다.", oauth_provider_not_supported: "OAuth 제공자가 비활성화되어 있습니다.",