diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/users/auth/verifyCredentails.ts | 81 |
1 files changed, 40 insertions, 41 deletions
diff --git a/lib/users/auth/verifyCredentails.ts b/lib/users/auth/verifyCredentails.ts index 5764db77..83a2f276 100644 --- a/lib/users/auth/verifyCredentails.ts +++ b/lib/users/auth/verifyCredentails.ts @@ -3,6 +3,8 @@ import bcrypt from 'bcryptjs'; import crypto from 'crypto'; +import fs from 'fs'; +import path from 'path'; import { eq, and, desc, gte, count } from 'drizzle-orm'; import db from '@/db/db'; import { @@ -423,34 +425,33 @@ export async function completeMfaAuthentication( } } - - - - // RSA 암호화 함수 function encryptPasswordWithRSA(password: string): string { try { - // 환경변수에서 RSA 키 가져오기 - const rsaKey = process.env.S_GIPS_RSA_KEY; - if (!rsaKey) { - throw new Error('RSA 키가 설정되지 않았습니다.'); + + // 파일에서 RSA 공개키 읽기 + const keyPath = path.join(process.cwd(), 'lib/users/auth/public_key.pem'); + + // 파일 존재 여부 확인 + if (!fs.existsSync(keyPath)) { + throw new Error(`RSA 키 파일을 찾을 수 없습니다: ${keyPath}`); } - // PEM 형태로 키 복원 (BEGIN/END 헤더 추가) - const publicKey = `-----BEGIN PUBLIC KEY-----\n${rsaKey}\n-----END PUBLIC KEY-----`; + const publicKey = fs.readFileSync(keyPath, 'utf8'); // RSA 공개키로 암호화 (Java와 동일한 OAEP 패딩 사용) - const encryptedBuffer = crypto.publicEncrypt( - { - key: publicKey, - padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, - oaepHash: 'sha256', - }, - Buffer.from(password, 'utf8') - ); + const encryptOptions = { + key: publicKey, + padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, + oaepHash: 'sha256', // Java: SHA-256 (MGF1 해시도 동일 값 사용됨) + }; + + const encryptedBuffer = crypto.publicEncrypt(encryptOptions, Buffer.from(password, 'utf8')); // Base64로 인코딩하여 반환 - return encryptedBuffer.toString('base64'); + const base64Result = encryptedBuffer.toString('base64'); + + return base64Result; } catch (error) { console.error('RSA 암호화 오류:', error); throw new Error('비밀번호 암호화에 실패했습니다.'); @@ -496,25 +497,14 @@ export async function verifySGipsCredentials( // password를 RSA로 암호화 const encryptedPassword = encryptPasswordWithRSA(password); - // URL에 query parameter 추가 (urlSearchParams 사용하는 경우 URL Safe하게 인코딩하기 때문에 fail 발생함) - const params = { + // URLSearchParams를 사용하여 특수문자를 안전하게 인코딩 + const params = new URLSearchParams({ Id: username, Passwd: encryptedPassword, - }; - - const requestUrl = `${sgipsUrl}?Id=${params.Id}&Passwd=${params.Passwd}`; - - - // 1. S-Gips API 호출로 인증 확인 - console.log('S-Gips API 요청:', { - url: requestUrl, - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${process.env.S_GIPS_TOKEN}`, - }, }); + const requestUrl = `${sgipsUrl}?${params.toString()}`; + const response = await fetch(requestUrl, { method: 'GET', headers: { @@ -523,15 +513,24 @@ export async function verifySGipsCredentials( }, }); - if (!response.ok) { - if (response.status === 401) { - return { success: false, error: 'INVALID_CREDENTIALS' }; - } - throw new Error(`API Error: ${response.status}`); - } + // 응답 본문을 한 번만 읽어서 재사용 + const responseText = await response.text(); - const data = await response.json(); + if (!response.ok && response.status == 401) { + console.error('유효하지 않은 S-GIPS JWT 응답코드 발생 :', response.status); + console.error('오류 응답 본문:', responseText); + return { success: false, error: 'INVALID_CREDENTIALS' }; + } + // 텍스트를 JSON으로 파싱 + let data; + try { + data = JSON.parse(responseText); + } catch (e) { + console.error('S-Gips Invalid JSON response:', e); + throw new Error('S-Gips Invalid JSON response'); + } + // 2. S-Gips API 응답 확인 if (data.message === "success" && data.code === "0") { // 3. username의 앞 8자리로 vendorCode 추출 |
