// SAML Identity Provider (IdP) 메타데이터 유틸리티 export interface IDPMetadata { entityId: string ssoUrl: string sloUrl?: string certificate: string nameIdFormat: string organization: string wantAuthnRequestsSigned: boolean } // IdP 메타데이터 가져오기 (환경변수 기반) export function getIDPMetadata(): IDPMetadata { console.log('🔍 Loading IdP metadata from environment variables...') // 필수 환경변수 검증 const entityId = process.env.SAML_IDP_ENTITY_ID const ssoUrl = process.env.SAML_IDP_SSO_URL const certificate = process.env.SAML_IDP_CERT if (!entityId || !ssoUrl || !certificate) { throw new Error('Required SAML IdP environment variables are missing: SAML_IDP_ENTITY_ID, SAML_IDP_SSO_URL, SAML_IDP_CERT') } const metadata: IDPMetadata = { entityId, ssoUrl, sloUrl: process.env.SAML_IDP_SLO_URL, certificate, nameIdFormat: process.env.SAML_IDP_NAME_ID_FORMAT || 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', organization: process.env.SAML_IDP_ORGANIZATION || 'Unknown Organization', wantAuthnRequestsSigned: process.env.SAML_IDP_WANT_AUTHN_REQUESTS_SIGNED === 'true' } console.log('✅ IdP metadata loaded from environment variables:', { entityId, ssoUrl, sloUrl: metadata.sloUrl, organization: metadata.organization, wantAuthnRequestsSigned: metadata.wantAuthnRequestsSigned }) return metadata } // 인증서 형식 정규화 (PEM 형식으로 변환) export function normalizeCertificate(cert: string): string { // 이미 PEM 형식인 경우 그대로 반환 if (cert.includes('-----BEGIN CERTIFICATE-----')) { return cert } // Base64 인증서를 PEM 형식으로 변환 (64자마다 줄바꿈) const cleanCert = cert.replace(/\s+/g, '') const formattedCert = cleanCert.match(/.{1,64}/g)?.join('\n') || cleanCert return `-----BEGIN CERTIFICATE-----\n${formattedCert}\n-----END CERTIFICATE-----` } // 특정 용도의 인증서 가져오기 export function getCertificateByUse(metadata: IDPMetadata, use: 'signing' | 'encryption'): string { const cert = metadata.certificates.find(c => c.use === use) return cert ? normalizeCertificate(cert.certificate) : '' } // 모든 인증서를 PEM 형식으로 변환 export function getAllCertificatesAsPEM(metadata: IDPMetadata): { use: string; pem: string }[] { return metadata.certificates.map(cert => ({ use: cert.use, pem: normalizeCertificate(cert.certificate) })) } // 레거시 호환성을 위한 함수 - 첫 번째 인증서를 문자열로 반환 export function getFirstCertificateAsString(metadata: IDPMetadata): string { return metadata.certificates[0]?.certificate || '' } // SP 메타데이터 생성을 위한 헬퍼 export function getSPEntityId(): string { return process.env.SAML_SP_ENTITY_ID || `${process.env.NEXTAUTH_URL}/saml/metadata` } export function getSPCallbackUrl(): string { return `${process.env.NEXTAUTH_URL}/api/saml/callback` }