From 022594f8dccc855f86efc92bf33bb4fbb5a94232 Mon Sep 17 00:00:00 2001 From: kyy Date: Fri, 10 Apr 2026 11:01:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9A=94=EC=B2=AD/=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 ++- public/app.js | 19 ++-- public/index.html | 2 +- server.js | 281 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 216 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 274db42..f8d24da 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## 주요 특징 - **Headless 인증**: IdP가 제공하는 UI를 거치지 않고, RP(데모 앱)가 사용자 자격 증명을 직접 받아 백채널로 인증을 수행합니다. -- **동적 UI 전환**: 입력값(숫자 vs 문자)을 실시간으로 분석하여 '전화번호 인증' 또는 '사번 로그인' 모드로 자동 전환됩니다. +- **동적 UI 전환**: 입력값(숫자 vs 문자)을 실시간으로 분석하여 '전화번호 SSO 인증' 또는 '사번 로그인' 모드로 자동 전환됩니다. - **Trusted RP 구현**: - **OIDC Discovery**: `sso-test.hmac.kr`의 메타데이터를 동적으로 로드합니다. - **JWKS Endpoint**: 서버 시작 시 생성된 RSA 공개키를 `/.well-known/jwks.json`을 통해 서빙하여 IdP와의 신뢰 관계를 형성합니다. @@ -29,6 +29,9 @@ CLIENT_ID=15cfb85c-f75f-4b51-a13d-d04f87d39739 ISSUER=https://sso-test.hmac.kr/oidc REDIRECT_URI=http://localhost:3000/callback JWKS_URI=http://localhost:3000/.well-known/jwks.json +# 필요 시 전화번호용 headless link endpoint를 별도로 덮어쓸 수 있음 +PHONE_HEADLESS_LINK_INIT_ENDPOINT= +PHONE_HEADLESS_LINK_POLL_ENDPOINT= ``` ### 2. 의존성 설치 @@ -58,12 +61,14 @@ npm start ### 1. 입력값 분류 (Classify Input) 사용자가 입력한 값이 숫자만 포함되어 있으면 전화번호(`phone`) 모드로, 문자가 포함되어 있으면 사번(`employee`) 모드로 인식합니다. -- **Phone**: 인증 링크 발송 시뮬레이션 실행. +- **Phone**: 전화번호를 SSO headless 인증 흐름에 전달합니다. - **Employee**: 비밀번호 입력란 노출 및 OIDC Password Grant 요청 실행. -### 2. OIDC Password Grant (Real Communication) -데모 앱은 사용자로부터 받은 `loginId`와 `password`를 SSO 서버의 토큰 엔드포인트로 직접 전달합니다. +### 2. SSO Headless 인증 (Real Communication) +데모 앱은 사용자로부터 받은 식별자와 자격 증명을 SSO 서버의 headless 인증 엔드포인트로 직접 전달합니다. - SSO 서버가 해당 방식을 허용하도록 설정되어 있어야 하며, 화이트리스트에 등록된 `REDIRECT_URI`와 일치해야 합니다. +- 전화번호 로그인은 `POST /api/v1/auth/headless/link/init`로 링크를 발송한 뒤 `POST /api/v1/auth/headless/link/poll`로 승인 완료를 기다리는 흐름입니다. +- 필요하면 `PHONE_HEADLESS_LINK_INIT_ENDPOINT`와 `PHONE_HEADLESS_LINK_POLL_ENDPOINT`로 오버라이드할 수 있습니다. ## 라이선스 이 프로젝트는 내부 테스트 및 데모 목적으로 제작되었습니다. diff --git a/public/app.js b/public/app.js index d080eeb..e8f5590 100644 --- a/public/app.js +++ b/public/app.js @@ -43,10 +43,10 @@ function updateUI() { } passwordField.classList.add('hidden'); - inputHint.textContent = '전화번호가 확인되었습니다. 인증링크 발송 흐름을 사용할 수 있습니다.'; + inputHint.textContent = '전화번호가 확인되었습니다. SSO 인증링크를 발송할 수 있습니다.'; submitButton.textContent = '인증링크 발송'; submitButton.disabled = value.replace(/\D/g, '').length < 10; - statusText.textContent = '인증링크 발송 단계를 준비했습니다.'; + statusText.textContent = '전화번호 기반 SSO 인증 단계를 준비했습니다.'; } else if (mode === 'employee') { passwordField.classList.remove('hidden'); inputHint.textContent = 'ID 입력이 확인되었습니다. 비밀번호를 입력해 로그인하세요.'; @@ -74,6 +74,9 @@ loginForm.addEventListener('submit', async (e) => { submitButton.disabled = true; const originalBtnText = submitButton.textContent; submitButton.textContent = '처리 중...'; + if (currentMode === 'phone') { + statusText.textContent = '휴대폰으로 인증링크를 발송하고 승인 완료를 기다리고 있습니다.'; + } try { let response; @@ -98,11 +101,13 @@ loginForm.addEventListener('submit', async (e) => { statusDisplay.classList.add('hidden'); successPanel.classList.remove('hidden'); - successTitle.textContent = currentMode === 'phone' ? '인증링크 발송 완료' : '로그인 성공'; - successDescription.textContent = currentMode === 'phone' - ? `${identifier} 번호로 인증 링크를 보냈습니다.` - : `${identifier} 계정으로 접속되었습니다. 잠시 후 홈 화면으로 이동합니다...`; - + if (currentMode === 'phone') { + successTitle.textContent = '전화번호 인증 완료'; + successDescription.textContent = result.message || `${identifier} 번호의 SSO 인증이 완료되었습니다.`; + } else { + successTitle.textContent = '로그인 성공'; + successDescription.textContent = `${identifier} 계정으로 접속되었습니다. 잠시 후 홈 화면으로 이동합니다...`; + } if (result.redirectTo) { setTimeout(() => { window.location.href = result.redirectTo; diff --git a/public/index.html b/public/index.html index 136e749..607eec5 100644 --- a/public/index.html +++ b/public/index.html @@ -11,7 +11,7 @@

PM 데모 로그인

-

숫자만 입력하면 전화번호 인증, 그 외 입력은 ID/PW 로그인으로 전환됩니다.

+

숫자만 입력하면 전화번호 SSO 인증, 그 외 입력은 ID/PW 로그인으로 전환됩니다.