Feat: 회원가입 직후 이메일 인증 완료 처리 추가

app/auth/callback/route.ts
- OAuth 콜백 처리 시 신규 사용자(생성 시간 1분 이내)를 감지하면 자동 로그인 세션을 종료하고 로그인 페이지로 리다이렉트하며 이메일 인증 완료 메시지를 전달하도록 로직 추가
- 일반 로그인은 기존처럼 코드 파라미터 제거 후 깔끔한 URL로 리다이렉트하도록 유지

features/auth/constants.ts
- 이메일 인증 성공 메시지 상수 추가
- 일부 문자열 포맷팅 정리
This commit is contained in:
2026-02-05 13:19:53 +09:00
parent aae7000807
commit 9c967af9c1
2 changed files with 31 additions and 3 deletions

View File

@@ -62,8 +62,33 @@ export async function GET(request: NextRequest) {
if (!exchangeError) { if (!exchangeError) {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// 3-1. 교환 성공: 리다이렉트 처리 // 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 forwardedHost = request.headers.get("x-forwarded-host"); // 로드밸런서 지원
const isLocalEnv = process.env.NODE_ENV === "development"; const isLocalEnv = process.env.NODE_ENV === "development";

View File

@@ -40,6 +40,7 @@ export const AUTH_ERROR_MESSAGES = {
// === 인증 링크 === // === 인증 링크 ===
INVALID_AUTH_LINK: "인증 링크가 만료되었거나 유효하지 않습니다.", INVALID_AUTH_LINK: "인증 링크가 만료되었거나 유효하지 않습니다.",
EMAIL_VERIFIED_SUCCESS: "이메일 인증이 완료되었습니다. 로그인해 주세요.",
// === 소셜 로그인 (OAuth) 관련 === // === 소셜 로그인 (OAuth) 관련 ===
OAUTH_ACCESS_DENIED: "로그인이 취소되었습니다.", OAUTH_ACCESS_DENIED: "로그인이 취소되었습니다.",
@@ -106,8 +107,10 @@ export const AUTH_ERROR_CODE_MESSAGES = {
mfa_verification_failed: "MFA 검증에 실패했습니다.", mfa_verification_failed: "MFA 검증에 실패했습니다.",
mfa_verification_rejected: "MFA 검증이 거부되었습니다.", mfa_verification_rejected: "MFA 검증이 거부되었습니다.",
mfa_verified_factor_exists: "이미 검증된 전화 MFA가 존재합니다.", mfa_verified_factor_exists: "이미 검증된 전화 MFA가 존재합니다.",
mfa_web_authn_enroll_not_enabled: "WebAuthn MFA 등록이 비활성화되어 있습니다.", mfa_web_authn_enroll_not_enabled:
mfa_web_authn_verify_not_enabled: "WebAuthn MFA 검증이 비활성화되어 있습니다.", "WebAuthn MFA 등록이 비활성화되어 있습니다.",
mfa_web_authn_verify_not_enabled:
"WebAuthn MFA 검증이 비활성화되어 있습니다.",
no_authorization: "Authorization 헤더가 필요합니다.", no_authorization: "Authorization 헤더가 필요합니다.",
not_admin: "관리자 권한이 없습니다.", not_admin: "관리자 권한이 없습니다.",
oauth_provider_not_supported: "OAuth 제공자가 비활성화되어 있습니다.", oauth_provider_not_supported: "OAuth 제공자가 비활성화되어 있습니다.",