From ebe273ef4564d55f9bf193adc51a9e58211e72e9 Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Mon, 23 Jun 2025 06:44:34 +0000
Subject: (김준회 SAML 2.0 SSO 리팩터링, 디버깅 유틸리티 추가, MOCK 처리 추가
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/api/auth/saml/authn-request/route.ts | 76 ++++++++++++-----
app/api/auth/saml/mock-idp/route.ts | 137 +++++++++++++++++++++++++++++++
2 files changed, 194 insertions(+), 19 deletions(-)
create mode 100644 app/api/auth/saml/mock-idp/route.ts
(limited to 'app/api/auth/saml')
diff --git a/app/api/auth/saml/authn-request/route.ts b/app/api/auth/saml/authn-request/route.ts
index e3cb8a47..f079aea0 100644
--- a/app/api/auth/saml/authn-request/route.ts
+++ b/app/api/auth/saml/authn-request/route.ts
@@ -1,45 +1,83 @@
-import { NextRequest, NextResponse } from 'next/server'
+/**
+ * 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'
-const samlEnvironment = {
- NODE_ENV: process.env.NODE_ENV,
- SAML_USE_MOCKUP: process.env.SAML_USE_MOCKUP,
- NEXTAUTH_URL: process.env.NEXTAUTH_URL,
-}
+// 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')
-// 환경변수 체크
-function checkEnvironment() {
- console.log('📊 Environment check:', JSON.stringify(samlEnvironment, null, 2))
+ // 키 없어도 구현 가능해서 주석 처리함.
+ // 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() {
- console.log('🚀 SAML AuthnRequest API started')
- checkEnvironment()
-
+ debugProcess('🚀 SAML AuthnRequest API started')
+
try {
- console.log('SSO STEP 1: Create AuthnRequest')
+ // 환경변수 검증
+ const environment = validateSAMLEnvironment()
+
+ debugProcess('SSO STEP 1: Create AuthnRequest')
const startTime = Date.now()
const loginUrl = await createAuthnRequest()
const endTime = Date.now()
- console.log('SAML AuthnRequest created successfully:', {
- url: loginUrl,
+ 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,
- mode: 'real',
- message: 'Using real SAML IdP'
+ isThisMocking: environment.SAML_MOCKING_IDP === 'true'
})
} catch (error) {
- console.error('Failed to create SAML AuthnRequest:', {
+ 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()
diff --git a/app/api/auth/saml/mock-idp/route.ts b/app/api/auth/saml/mock-idp/route.ts
new file mode 100644
index 00000000..45c670b0
--- /dev/null
+++ b/app/api/auth/saml/mock-idp/route.ts
@@ -0,0 +1,137 @@
+import { NextRequest, NextResponse } from 'next/server'
+
+// Mock IdP 엔드포인트 - SAML Response HTML 폼 반환
+export async function GET(request: NextRequest) {
+ try {
+ console.log('🎭 Mock IdP endpoint accessed');
+
+ // Mock SAML Response 데이터 (실제 형태와 일치하도록 문자열 형태)
+ const mockSAMLResponseData = {
+ nameID: "testuser@samsung.com",
+ nameIDFormat: "urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress",
+ attributes: {
+ email: "testuser@samsung.com",
+ name: "홍길동",
+ }
+ };
+
+ // Mock XML SAML Response 생성
+ const mockXML = `
+
테스트 사용자 정보:
+5초 후 자동으로 로그인을 진행합니다...
+프로덕션 환경에서는 SAML_MOCKING_IDP=false로 설정하세요.
+