diff options
Diffstat (limited to 'app/api/auth/saml/authn-request/route.ts')
| -rw-r--r-- | app/api/auth/saml/authn-request/route.ts | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/app/api/auth/saml/authn-request/route.ts b/app/api/auth/saml/authn-request/route.ts new file mode 100644 index 00000000..6544a765 --- /dev/null +++ b/app/api/auth/saml/authn-request/route.ts @@ -0,0 +1,98 @@ +/** + * SAML 2.0 SSO AuthnRequest 생성 API + * + * 역할: + * - 프론트엔드에서 SAML 로그인 URL을 요청할 때 사용 + * - SAML AuthnRequest를 생성하고 IdP 로그인 URL 반환 + * - Mock 모드 지원으로 개발/테스트 환경에서 시뮬레이션 가능 + * + * 플로우: + * 1. 사용자가 "Knox SSO로 로그인" 버튼 클릭 + * 2. 프론트엔드에서 이 API 호출 + * 3. SAML AuthnRequest URL 생성 후 반환 + * 4. 프론트엔드에서 해당 URL로 리다이렉트 + * 5. IdP에서 인증 후 /api/saml/callback으로 SAML Response 전송 + */ + +import { NextResponse } from 'next/server' +import { createAuthnRequest } from '../../[...nextauth]/saml/utils' +import { debugLog, debugError, debugSuccess, debugProcess } from '@/lib/debug-utils' + +// SAML 환경변수 상태 체크 +function validateSAMLEnvironment() { + const samlEnvironment = { + NODE_ENV: process.env.NODE_ENV, + SAML_MOCKING_IDP: process.env.SAML_MOCKING_IDP, + NEXTAUTH_URL: process.env.NEXTAUTH_URL, + SAML_SP_PRIVATE_KEY: process.env.SAML_SP_PRIVATE_KEY ? '✅ Set' : '❌ Missing', + SAML_SP_CERT: process.env.SAML_SP_CERT ? '✅ Set' : '❌ Missing', + } + + debugLog('📊 SAML Environment check:', JSON.stringify(samlEnvironment, null, 2)) + + // 필수 환경변수 검증 + const missingVars = [] + if (!process.env.NEXTAUTH_URL) missingVars.push('NEXTAUTH_URL') + + // 키 없어도 구현 가능해서 주석 처리함. + // if (!process.env.SAML_SP_PRIVATE_KEY) missingVars.push('SAML_SP_PRIVATE_KEY') + // if (!process.env.SAML_SP_CERT) missingVars.push('SAML_SP_CERT') + + if (missingVars.length > 0) { + throw new Error(`Missing required SAML environment variables: ${missingVars.join(', ')}`) + } + + return samlEnvironment +} + +/** + * SAML AuthnRequest URL 생성 엔드포인트 + * + * @returns {JSON} { loginUrl: string, success: boolean, isThisMocking?: boolean } + */ +export async function GET(request: Request) { + debugProcess('🚀 SAML AuthnRequest API started') + + try { + // URL에서 RelayState 매개변수 추출 + const url = new URL(request.url) + const relayState = url.searchParams.get('relayState') + + debugLog('RelayState parameter:', relayState) + + // 환경변수 검증 + const environment = validateSAMLEnvironment() + + debugProcess('SSO STEP 1: Create AuthnRequest') + + const startTime = Date.now() + const loginUrl = await createAuthnRequest(relayState || undefined) + const endTime = Date.now() + + debugSuccess('SAML AuthnRequest created successfully:', { + url: loginUrl.substring(0, 100) + '...', + urlLength: loginUrl.length, + processingTime: `${endTime - startTime}ms`, + mockMode: environment.SAML_MOCKING_IDP === 'true', + timestamp: new Date().toISOString() + }) + + return NextResponse.json({ + loginUrl, + success: true, + isThisMocking: environment.SAML_MOCKING_IDP === 'true' + }) + } catch (error) { + debugError('Failed to create SAML AuthnRequest:', { + error: error instanceof Error ? error.message : 'Unknown error', + stack: error instanceof Error ? error.stack : undefined, + timestamp: new Date().toISOString() + }) + + return NextResponse.json({ + error: 'Failed to create SAML AuthnRequest', + details: error instanceof Error ? error.message : 'Unknown error', + success: false + }, { status: 500 }) + } +} |
