diff options
| author | joonhoekim <26rote@gmail.com> | 2025-06-23 12:56:54 +0000 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-06-23 12:56:54 +0000 |
| commit | 1e46c2f3523f0f73a7ed378e9281dec24b23f8f8 (patch) | |
| tree | 62438a757a4aadc8d9aa6924bd3756a919fe2303 /app/api/saml | |
| parent | ebe273ef4564d55f9bf193adc51a9e58211e72e9 (diff) | |
(김준회) SAML 2.0 relay-state 처리 및 redirect 상태코드 문제 디버깅
Diffstat (limited to 'app/api/saml')
| -rw-r--r-- | app/api/saml/callback/route.ts | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/app/api/saml/callback/route.ts b/app/api/saml/callback/route.ts index cf9ea772..7f454cb9 100644 --- a/app/api/saml/callback/route.ts +++ b/app/api/saml/callback/route.ts @@ -12,18 +12,16 @@ import { debugLog, debugError, debugSuccess, debugProcess } from '@/lib/debug-ut // GET 요청시 SP 메타데이터를 반환해주는데, 이건 필요 없으면 지우면 된다. export async function POST(request: NextRequest) { + // 안전한 baseUrl - 모든 리다이렉트에서 사용 + const baseUrl = process.env.NEXTAUTH_URL || 'http://localhost:3000'; + try { const isMockMode = process.env.SAML_MOCKING_IDP === 'true'; debugProcess(`SAML Callback received at /api/saml/callback ${isMockMode ? '(🎭 Mock Mode)' : ''}`) debugLog('Request info:', { - url: request.url, nextUrl: request.nextUrl?.toString(), mockMode: isMockMode, - headers: { - host: request.headers.get('host'), - origin: request.headers.get('origin'), - referer: request.headers.get('referer') - } + baseUrl: baseUrl }) // FormData에서 SAML Response 추출 @@ -75,10 +73,7 @@ export async function POST(request: NextRequest) { if (!samlResponse) { debugError('No SAML Response found in request') - const baseUrl = request.url || process.env.NEXTAUTH_URL || 'http://localhost:3000' - return NextResponse.redirect( - new URL('/ko/evcp', baseUrl) - ) + return NextResponse.redirect(new URL('/ko/evcp', baseUrl), 303) } // SAML Response 검증 및 파싱 @@ -99,10 +94,7 @@ export async function POST(request: NextRequest) { }) // SAML 검증 실패 시 evcp 페이지로 리다이렉트 - const baseUrl = request.url || process.env.NEXTAUTH_URL || 'http://localhost:3000' - return NextResponse.redirect( - new URL('/ko/evcp', baseUrl) - ) + return NextResponse.redirect(new URL('/ko/evcp', baseUrl), 303) } // SAML 프로필을 사용자 객체로 매핑 @@ -121,8 +113,7 @@ export async function POST(request: NextRequest) { if (!authenticatedUser) { debugError('SAML user authentication failed') - const baseUrl = request.url || process.env.NEXTAUTH_URL || 'http://localhost:3000' - return NextResponse.redirect(new URL('/ko/evcp', baseUrl)) + return NextResponse.redirect(new URL('/ko/evcp', baseUrl), 303) } debugSuccess('User authenticated successfully:', { @@ -137,7 +128,38 @@ export async function POST(request: NextRequest) { // NextAuth 세션 쿠키 설정 const cookieName = getSessionCookieName() - const response = NextResponse.redirect(new URL('/ko/evcp', request.url || process.env.NEXTAUTH_URL || 'http://localhost:3000')) + // RelayState를 활용한 스마트 리다이렉트 + let redirectPath = '/ko/evcp' // 기본값 + + // RelayState 안전 처리 - null, 'null', undefined, 빈 문자열 모두 처리 + const isValidRelayState = relayState && + relayState !== 'null' && + relayState !== 'undefined' && + relayState.trim() !== '' && + typeof relayState === 'string'; + + if (isValidRelayState) { + debugLog('Using RelayState for redirect:', relayState) + // RelayState가 유효한 경로인지 확인 + if (relayState.startsWith('/') && !relayState.includes('//')) { + redirectPath = relayState + } else { + debugLog('Invalid RelayState format, using default:', relayState) + } + } else { + debugLog('No valid RelayState, using default path. RelayState value:', relayState) + } + + // URL 생성 전 최종 안전성 검사 + if (!redirectPath || typeof redirectPath !== 'string' || redirectPath.trim() === '') { + redirectPath = '/ko/evcp' // 안전한 기본값으로 재설정 + debugLog('redirectPath was invalid, reset to default:', redirectPath) + } + + debugLog('Final redirect path:', redirectPath) + + // POST 요청에 대한 응답으로는 303 See Other를 사용하여 GET으로 강제 변환 + const response = NextResponse.redirect(new URL(redirectPath, baseUrl), 303) response.cookies.set(cookieName, encodedToken, { httpOnly: true, @@ -153,10 +175,7 @@ export async function POST(request: NextRequest) { } catch (error) { debugError('SAML Callback processing failed:', error) - const baseUrl = request.url || process.env.NEXTAUTH_URL || 'http://localhost:3000' - return NextResponse.redirect( - new URL('/ko/evcp', baseUrl) - ) + return NextResponse.redirect(new URL('/ko/evcp', baseUrl), 303) } } |
