diff --git a/baron-sso_login_guide/BARONSSO_loginAPI_task.md b/baron-sso_login_guide/BARONSSO_loginAPI_task.md
new file mode 100644
index 0000000..e7722d4
--- /dev/null
+++ b/baron-sso_login_guide/BARONSSO_loginAPI_task.md
@@ -0,0 +1,132 @@
+# BARON-SSO 통합 로그인 연동 가이드 (자산관리 시스템)
+
+이 문서는 Baron SSO(OpenID Connect IdP)를 자산관리 시스템에 통합 연동하기 위한 상세 가이드입니다. Headless 로그인 방식과 OIDC 표준을 기반으로 사용자 인증 및 정보 획득 과정을 설명하며, Baron SSO `devfront` 페이지에서의 애플리케이션 설정 방법과 연동 시 필요한 핵심 로직을 다룹니다.
+
+---
+
+## 1. 개요
+
+자산관리 시스템에 Baron SSO를 연동하여 통합 로그인을 구현합니다. 이를 통해 사용자는 Baron SSO에서 인증하고, 자산관리 시스템은 사용자의 신원을 확인하고 필요한 정보를 획득하게 됩니다. 본 가이드는 주로 **Headless 로그인** 방식을 사용하며, 이는 사용자에게 Baron SSO의 로그인 화면을 직접 노출하지 않고 자산관리 시스템 내에서 인증 과정을 처리하는 방식입니다.
+
+---
+
+## 2. OIDC 핵심 개념
+
+### 2.1. Headless Login
+사용자가 IdP(Baron SSO)의 로그인 화면을 거치지 않고, RP(Relying Party, 자산관리 시스템) 내에서 직접 사용자 인증 정보를 입력받아 백채널(Back-channel)로 인증을 수행하는 방식입니다.
+
+### 2.2. Client Assertion
+보안 강화를 위해 RP가 자신이 신뢰할 수 있는 앱임을 증명하는 JWT(JSON Web Token)입니다. 이는 중요한 인증 요청 시 함께 전송됩니다.
+
+### 2.3. 스코프 (Scopes)
+사용자 정보에 접근하기 위한 권한 요청 단위입니다.
+- `openid`: OIDC 인증 요청임을 명시하며 `id_token` 발급에 필수적입니다.
+- `profile`: 사용자의 기본 프로필 정보(이름, 사번, 부서명 등) 접근 권한을 요청합니다.
+- `email`: 사용자의 이메일 주소 정보 접근 권한을 요청합니다.
+
+### 2.4. 자동 승인 (Auto-Consent)
+Headless 환경에서 사용자의 정보 제공 동의 화면 없이, RP 서버가 백그라운드에서 동의 과정을 자동으로 처리하는 로직입니다.
+
+---
+
+## 3. Baron SSO (devfront) 애플리케이션 생성 및 설정
+
+자산관리 시스템을 Baron SSO에 연동하기 위해 `devfront` 관리자 도구에서 Headless RP를 설정해야 합니다. 이때 IdP 서버가 RP의 JWKS 엔드포인트에 접속할 수 있어야 함을 유의하십시오.
+
+### 3.1. Step 1: 클라이언트 기본 정보 입력
+
+1. `devfront`에 접속하여 **연동 앱 > 연동 앱 추가**를 클릭합니다.
+2. **Name**: `asset-management-system` (또는 자산관리 시스템의 이름을 입력)
+3. **Redirect URIs**: 자산관리 시스템의 콜백 경로를 입력합니다.
+ - 예: `http://[자산관리_시스템_IP_또는_도메인]:[포트]/callback`
+ - **주의**: 실제 자산관리 시스템에서 요청하는 Redirect URI와 여기서 등록한 값이 **완전히 일치**해야 인증 거부 에러가 발생하지 않습니다.
+4. **Scopes**: `openid`, `profile`, `email`을 선택합니다.
+5. **Type**: 반드시 `pkce`를 선택합니다.
+
+### 3.2. Step 2: Headless 기능 및 보안 설정
+
+1. `pkce` 하단의 **"Headless Login (자체 로그인 UI 사용)"** 토글을 활성화합니다.
+2. **JWKS URI**: **Baron SSO 서버에서 접근 가능한** 자산관리 시스템의 공개키 주소를 입력합니다.
+ - 예: `http://[자산관리_시스템_IP_또는_도메인]:[포트]/.well-known/jwks.json`
+ - **주의**: Baron SSO 서버에서 자산관리 시스템의 포트로 네트워크가 열려있어야 합니다.
+
+### 3.3. Step 3: 저장 및 확인 (JWKS 캐시 검증)
+
+1. **앱 생성** 버튼을 클릭하여 설정을 저장합니다.
+2. 연동 앱 목록에서 생성된 앱이 **PKCE (Headless Login)** 유형인지 확인합니다.
+3. 앱 상세 페이지 하단이나 설정 탭에서 **JWKS 캐시 상태**가 `Success`인지 반드시 확인합니다. 캐시 상태가 비어있거나 실패인 경우, 자산관리 시스템이 켜져 있는지 확인하고 **새로고침(Refresh)** 버튼을 눌러 수동으로 캐시를 갱신해야 합니다.
+
+---
+
+## 4. 자산관리 시스템 연동 로직
+
+### 4.1. 사번 로그인 (Headless Employee ID Login Flow)
+
+사용자가 자산관리 시스템에서 사번과 비밀번호를 입력하여 로그인하는 시퀀스입니다.
+
+1. **신호 요청**: 자산관리 시스템은 Baron SSO의 Authorization Endpoint(`oauth2/auth`)에 요청하여 `login_challenge`를 획득합니다.
+2. **본인 인증**: 자산관리 시스템은 Private Key로 서명된 `client_assertion`(JWT)과 사용자의 사번, 비밀번호, `login_challenge`를 포함하여 Baron SSO의 Headless 로그인 API(`POST /api/v1/auth/headless/password/login`)를 호출합니다.
+3. **권한 획득 (자동 승인 포함)**: 인증 성공 후 Baron SSO가 반환하는 `redirectTo` 주소를 추적하며, 이 과정에서 `consent` 화면이 감지되면 자산관리 시스템은 백그라운드에서 동의 API(`POST /api/v1/auth/consent/accept`)를 호출하여 자동으로 승인합니다. 최종적으로 `Authorization Code`를 획득합니다.
+4. **인증키 발급**: 획득한 `Authorization Code`와 새로 생성한 `client_assertion`을 사용하여 Baron SSO의 Token Endpoint에 요청, `id_token`과 `access_token`을 발급받습니다.
+5. **로그인 완료**: `id_token`을 검증하고 사용자 정보를 추출하여 자산관리 시스템의 세션을 생성하고 로그인 완료 처리합니다.
+
+### 4.2. 전화번호 인증 로그인 (Headless Phone Number Authentication Login Flow)
+
+사용자가 자산관리 시스템에서 전화번호를 입력하여 인증 링크를 받고, 모바일에서 승인하여 로그인하는 시퀀스입니다.
+
+1. **신호 요청**: 사번 로그인과 동일하게 `login_challenge`를 획득합니다.
+2. **링크 발송 요청**: 자산관리 시스템은 `client_assertion`, `login_challenge`, 사용자의 전화번호(`loginId`)를 포함하여 Baron SSO의 인증 링크 발송 API(`POST /api/v1/auth/headless/link/init`)를 호출합니다. Baron SSO는 사용자에게 인증 링크를 발송하고 `pendingRef`를 반환합니다.
+3. **인증 상태 폴링**: 자산관리 시스템은 `pendingRef`와 `client_assertion`을 포함하여 Baron SSO의 상태 확인 API(`POST /api/v1/auth/headless/link/poll`)를 주기적으로 호출합니다. 사용자가 모바일에서 링크를 클릭하여 인증을 완료하면, Baron SSO는 `redirectTo` 정보를 반환하며 폴링이 종료됩니다.
+4. **이후 과정**: 폴링 결과로 받은 `redirectTo` 주소부터는 사번 로그인과 동일하게 표준 OIDC 흐름을 따릅니다 (자동 승인, `Authorization Code` 획득, `id_token` 발급, 세션 생성).
+
+### 4.3. 자동 승인 및 스코프 처리 (Auto-Consent and Scope Handling)
+
+자산관리 시스템은 `openid`, `profile`, `email`과 같은 스코프를 Baron SSO에 요청합니다. Headless 환경에서는 SSO 서버로부터 리다이렉트 주소에 `/consent`가 포함될 경우, 자산관리 시스템은 이를 감지하여 `consent_challenge`를 추출하고, 동의 상세 정보(`GET /api/v1/auth/consent`)를 요청하여 필요한 스코프를 확인합니다. 이후, 확인된 스코프를 모두 허용(`grant_scope`)한다고 Baron SSO의 동의 승인 API(`POST /api/v1/auth/consent/accept`)에 전송하여 자동으로 승인 과정을 처리합니다.
+
+### 4.4. Tenant 접근 제한 예외 처리 (Tenant Access Restriction Exception Handling)
+
+자산관리 시스템이 `tenant_access_restricted=true`로 설정되어 있고, 현재 사용자의 tenant가 허용된 `allowed_tenants`에 포함되지 않는 경우, Baron SSO는 `403` HTTP 상태 코드와 `code=tenant_not_allowed`를 응답합니다. 자산관리 시스템은 이 응답을 감지하여 사용자에게 적절한 에러 페이지(예: `/ko/error?error=tenant_not_allowed...`)로 리다이렉트하여 처리해야 합니다.
+
+---
+
+## 5. 자산관리 시스템 로컬 설정 (.env)
+
+자산관리 시스템 프로젝트 루트의 `.env` 파일에 다음과 같이 Baron SSO 연동 설정을 구성합니다.
+
+```env
+# 애플리케이션 실행 포트 (자산관리 시스템의 포트)
+PORT=3000 # 예시
+
+# OIDC IdP 설정 (Baron SSO 서버 주소)
+CLIENT_ID=... # devfront에서 발급받은 클라이언트 ID
+ISSUER=http://[BARON_SSO_IP_또는_도메인]/oidc
+
+# 리다이렉트 및 보안 설정
+# REDIRECT_URI는 DevFront에 등록한 Redirect URIs 중 하나와 정확히 일치해야 합니다.
+REDIRECT_URI=http://[자산관리_시스템_IP_또는_도메인]:[포트]/callback
+# JWKS_URI는 Baron SSO 서버가 자산관리 시스템으로 접속할 때 사용하는 주소와 일치해야 합니다.
+JWKS_URI=http://[자산관리_시스템_IP_또는_도메인]:[포트]/.well-known/jwks.json
+
+# tenant 제한 시 이동시킬 userfront 에러 경로
+ERROR_LOCALE_PATH=/ko/error
+```
+
+---
+
+## 6. 주의 사항 (네트워크 구성)
+
+- **서버 간 통신 (Server-to-Server)**: Headless 로그인은 Baron SSO 서버가 직접 자산관리 시스템의 `JWKS_URI`에 접속하여 서명을 검증합니다. 따라서 IdP 서버에서 자산관리 시스템의 포트로의 인바운드 통신이 허용되어야 합니다. 방화벽 및 네트워크 설정을 확인하십시오.
+- **Redirect URI 일치**: 브라우저를 통해 접속할 주소가 IP라면, Redirect URI와 JWKS URI 모두 IP 기반 주소로 통일하는 것이 문제 발생 소지를 줄이는 가장 좋은 방법입니다. 도메인을 사용한다면 일관되게 도메인으로 설정해야 합니다.
+
+---
+
+## 7. 실행
+
+자산관리 시스템 프로젝트에서 다음 명령어를 실행하여 필요한 패키지를 설치하고 서버를 시작합니다.
+
+```bash
+npm install
+npm start
+```
+
+서버 실행 시 `keys.json` 파일이 자동으로 생성되며, `.env`에 설정된 `JWKS_URI` 경로로 공개키가 서빙되어 Baron SSO가 이를 검증에 사용할 수 있게 됩니다.
diff --git a/baron-sso_login_guide/headless-consent-and-scope.md b/baron-sso_login_guide/headless-consent-and-scope.md
new file mode 100644
index 0000000..faa07fd
--- /dev/null
+++ b/baron-sso_login_guide/headless-consent-and-scope.md
@@ -0,0 +1,119 @@
+# Headless 스코프(Scope) 및 자동 승인(Auto-Consent) 가이드
+
+이 문서는 Headless 로그인 환경에서 애플리케이션이 사용자 정보를 가져오기 위해 사용하는 **스코프(Scope)**의 개념과, IdP의 화면 없이 권한을 획득하는 **자동 승인(Auto-Consent)** 로직을 설명합니다.
+
+---
+
+## 1. 요구 스코프 (Requested Scopes)
+
+데모 앱은 OIDC 표준에 따라 다음 스코프를 IdP(Baron SSO)에 요청합니다.
+
+| 스코프 | 필수 여부 | 역할 및 획득 데이터 |
+| :-------- | :-------: | :------------------------------------------------------------------ |
+| `openid` | **필수** | 해당 요청이 OIDC 인증임을 명시. `id_token` 발급을 위해 반드시 필요. |
+| `profile` | 권장 | 사용자의 기본 프로필 정보(이름, 사번, 부서명 등) 접근 권한. |
+| `email` | 권장 | 사용자의 이메일 주소 정보 접근 권한. |
+
+데모 앱은 최초 인증 요청(`GET /oauth2/auth`) 시 `scope=openid profile` 형식으로 권한을 요구합니다.
+
+---
+
+## 2. 자동 승인(Auto-Consent) 흐름도
+
+일반적인 OIDC 환경에서는 사용자에게 '정보 제공 동의' 화면이 노출되지만, Headless 환경에서는 **RP 서버가 이 과정을 백그라운드에서 자동으로 수행**합니다.
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Browser as 사용자 브라우저
+ participant RP as 데모 앱 서버 (RP)
+ participant SSO as Baron SSO (IdP)
+
+ RP->>SSO: 1. 본인 인증 요청 (전화번호)
+ SSO-->>RP: 2. 인증 성공 및 리다이렉트 (redirectTo: /consent...)
+
+ Note over RP: [자동 승인 로직 시작]
+ RP->>RP: 3. 리다이렉트 경로 중 '/consent' 감지
+ RP->>SSO: 4. 동의 상세 정보 요청 (GET /api/v1/auth/consent)
+ SSO-->>RP: 5. 요청된 스코프 정보 반환 (openid, profile 등)
+
+ RP->>SSO: 6. 동의 승인 API 호출 (POST /api/v1/auth/consent/accept)
[grant_scope 포함]
+ SSO-->>RP: 7. 최종 리다이렉트 주소 반환 (code=...)
+
+ Note over RP: [표준 OIDC 흐름 복귀]
+ RP->>SSO: 8. Token Exchange (Code -> id_token)
+ SSO-->>RP: 9. 사용자 정보가 담긴 id_token 발급
+ RP-->>Browser: 10. 세션 생성 및 로그인 완료 안내
+```
+---
+
+## 3. 핵심 구현 코드 (server.js)
+
+데모 앱의 `server.js` 내 `resolveRedirects` 함수는 SSO 서버로부터 오는 리다이렉트 주소를 추적하다가, 동의 화면(`consent_challenge`)이 나타나면 이를 가로채서 처리합니다.
+
+```javascript
+if (currentUrl.includes("/consent")) {
+ console.log(
+ " [자동 승인] 사용자의 정보 제공 동의 화면이 감지되어 시스템이 자동으로 승인 중입니다.",
+ );
+
+ // 1. URL에서 consent_challenge 추출
+ const consentUrl = new URL(currentUrl);
+ const consentChallenge = consentUrl.searchParams.get("consent_challenge");
+
+ // 2. SSO 서버에 현재 요청된 스코프가 무엇인지 확인
+ const detailsUrl = new URL("/api/v1/auth/consent", currentUrl);
+ detailsUrl.searchParams.set("consent_challenge", consentChallenge);
+ const detailsRes = await fetch(detailsUrl.toString(), {
+ headers: { Cookie: nextCookies },
+ });
+ const consentInfo = await detailsRes.json();
+
+ // 3. 확인된 스코프(openid, profile 등)를 모두 허용(accept)한다고 서버에 전송
+ const acceptUrl = new URL("/api/v1/auth/consent/accept", currentUrl);
+ const acceptRes = await fetch(acceptUrl.toString(), {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Cookie: nextCookies },
+ body: JSON.stringify({
+ consent_challenge: consentChallenge,
+ grant_scope: consentInfo.requested_scope || ["openid", "profile"],
+ grant_access_token_audience:
+ consentInfo.requested_access_token_audience || [],
+ }),
+ });
+
+ const acceptPayload = await acceptRes.json();
+ // 4. 승인 후 받은 최종 목적지(code 포함)로 이동 계속
+ return resolveRedirects(acceptPayload.redirectTo, nextCookies, depth + 1);
+}
+```
+
+## 4. Tenant 접근 제한 예외 흐름
+
+Headless RP도 consent 단계에서 tenant 제한에 걸릴 수 있습니다. 이 경우는 일반적인 auto-consent 성공 흐름과 별도로 처리해야 합니다.
+
+조건:
+- RP metadata에 `tenant_access_restricted=true`
+- 현재 사용자의 tenant가 `allowed_tenants`에 없음
+
+이때 Baron SSO 응답:
+- `GET /api/v1/auth/consent` 또는 `POST /api/v1/auth/consent/accept`
+- HTTP `403`
+- body에 `code=tenant_not_allowed`
+
+데모 앱 처리 원칙:
+- `redirectTo`가 없다고 가정하고 계속 진행하면 안 됩니다.
+- `tenant_not_allowed`를 감지하면 `userfront` 에러 화면 URL로 변환해 브라우저를 이동시켜야 합니다.
+- 기본 목적지는 `/ko/error?error=tenant_not_allowed&error_description=...&details=...` 입니다.
+
+운영 관점 해석:
+- backend 로그에 `tenant_not_allowed`가 보이면 Baron SSO 제한은 정상입니다.
+- 브라우저에서 `Invalid URL`이 보이면 RP가 `403` 응답을 잘못 소비하고 있다는 뜻입니다.
+
+---
+
+## 4. 특징 및 장점
+
+- **심리스한 UX**: 사용자는 "로그인 중..."이라는 메시지만 보게 되며, 복잡한 권한 동의 절차를 신경 쓸 필요가 없습니다.
+- **강력한 보안**: 자동 승인 과정은 서버 대 서버(Back-channel) 통신으로 이루어지며, 브라우저에는 동의 관련 데이터가 전혀 노출되지 않습니다.
+- **유연한 확장**: 나중에 새로운 사용자 정보(`email` 등)가 필요해지더라도, 앱의 스코프 설정만 변경하면 자동으로 승인 로직에 반영됩니다.
diff --git a/baron-sso_login_guide/headless-employee-login-flow.md b/baron-sso_login_guide/headless-employee-login-flow.md
new file mode 100644
index 0000000..2f2fd4f
--- /dev/null
+++ b/baron-sso_login_guide/headless-employee-login-flow.md
@@ -0,0 +1,95 @@
+# Headless 사번 로그인 로직
+
+이 문서는 사용자가 데모 애플리케이션에서 **사번과 비밀번호**를 이용해 로그인할 때 발생하는 내부 OIDC (OpenID Connect) Headless 인증 흐름을 설명합니다.
+
+## 핵심 개념
+
+- **Headless Login**: 사용자가 IdP(Identity Provider, Baron SSO)의 로그인 화면을 거치지 않고, RP(Relying Party, 데모 앱) 내에서 직접 아이디와 비밀번호를 입력받아 백채널(Back-channel)로 인증을 수행하는 방식입니다.
+- **Client Assertion**: 보안을 위해 데모 앱은 사번/비밀번호를 전송할 때 자신이 신뢰할 수 있는 앱임을 증명하는 JWT(`client_assertion`)를 생성하여 함께 전송합니다.
+
+---
+
+## 1. 사번 로그인 시퀀스 다이어그램
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant RP as 데모 앱 (RP)
+ participant OIDC as Baron SSO (OIDC/Hydra)
+ participant Auth as Baron SSO (Headless API)
+
+ User->>RP: 1. 사번 / 비밀번호 입력 후 로그인 요청
+
+ note over RP: [1단계: 신호 요청]
+ RP->>OIDC: 2. OIDC Discovery 및 Authorization Request
(GET /oauth2/auth?response_type=code...)
+ OIDC-->>RP: 3. login_challenge 발급 및 302 Redirect
+
+ note over RP: [2단계: 본인 인증]
+ RP->>RP: 4. Private Key로 client_assertion (JWT) 생성
+ RP->>Auth: 5. Headless 로그인 API 호출
(POST /api/v1/auth/headless/password/login)
[client_assertion, login_challenge, 사번, 비밀번호 포함]
+ Auth-->>RP: 6. 인증 성공 및 리다이렉트 URL 반환
+
+ note over RP: [3단계: 권한 획득]
+ RP->>OIDC: 7. 리다이렉트 URL 추적 (Cookie 유지)
+ OIDC-->>RP: 8. Consent 화면 (필요 시 자동 승인 API 호출)
+ OIDC-->>RP: 9. 최종 Authorization Code 발급 (code=...)
+
+ note over RP: [4단계: 인증키 발급]
+ RP->>OIDC: 10. Token Endpoint 호출 (Authorization Code Grant)
[client_assertion 포함]
+ OIDC-->>RP: 11. id_token, access_token 발급
+
+ note over RP: [5단계: 로그인 완료]
+ RP->>RP: 12. id_token 검증 및 사용자 세션 생성
+ RP-->>User: 13. 홈 화면 리다이렉트 및 로그인 성공
+```
+
+---
+
+## 2. 단계별 상세 로직 설명
+
+위 다이어그램의 주요 단계를 데모 애플리케이션(`server.js`의 `runHeadlessSsoLogin` 함수) 로직을 중심으로 설명합니다.
+
+### [1단계] 신호 요청 (Authorization Request)
+- **목적**: SSO 서버와의 세션을 시작하고, 인증 컨텍스트를 식별할 수 있는 고유값(`login_challenge`)을 획득합니다.
+- **동작**:
+ 1. OIDC Discovery를 통해 엔드포인트들을 가져옵니다.
+ 2. `response_type=code`, `client_id`, `state`, `nonce` 등을 포함하여 Authorization Endpoint(`/oauth2/auth`)로 `fetch` 요청(리다이렉트 수동 추적 모드)을 보냅니다.
+ 3. 응답 헤더의 `Location`에 포함된 `login_challenge` 값을 추출합니다.
+
+### [2단계] 본인 인증 (Headless Password Login)
+- **목적**: 사용자가 입력한 자격 증명(사번, 비밀번호)을 SSO 서버에 직접 전달하여 인증을 승인받습니다.
+- **동작**:
+ 1. RP의 **Private Key(`keys.json`)**를 사용하여 `client_assertion` JWT를 서명합니다. (이때 `aud` 값은 SSO 서버의 Headless API URL이어야 합니다.)
+ 2. `POST /api/v1/auth/headless/password/login` 엔드포인트로 JSON 페이로드를 전송합니다.
+ ```json
+ {
+ "client_id": "...",
+ "login_challenge": "...",
+ "loginId": "사번",
+ "password": "비밀번호",
+ "client_assertion": "..."
+ }
+ ```
+ 3. 인증이 성공하면 서버는 OIDC 로그인 흐름을 계속할 수 있는 `redirectTo` 주소를 반환합니다.
+
+### [3단계] 권한 획득 (Redirect Resolution & Consent)
+- **목적**: 인증 성공 후, OIDC 프로토콜에 따라 최종적으로 `Authorization Code`를 획득합니다.
+- **동작**:
+ 1. 2단계에서 받은 `redirectTo` 주소를 따라가며 쿠키(Cookie)를 계속 유지시킵니다.
+ 2. 만약 경로 중에 정보 제공 동의(`consent`) 화면이 감지되면, 데모 앱이 사용자 대신 백그라운드에서 동의 API(`POST /api/v1/auth/consent/accept`)를 호출하여 자동 승인합니다.
+ 3. 최종적으로 URL에 `code=...`가 포함된 리다이렉트를 찾습니다.
+
+### [4단계] 인증키 발급 (Token Exchange)
+- **목적**: 획득한 `Authorization Code`를 안전한 토큰들로 교환합니다.
+- **동작**:
+ 1. Token Endpoint로 코드를 전송합니다.
+ 2. 이때도 보안을 위해 `private_key_jwt` 방식이 사용되므로, 새로 생성한 `client_assertion`을 요청 본문에 포함시킵니다.
+ 3. 검증이 완료되면 `access_token`과 사용자 정보가 담긴 `id_token`을 받게 됩니다.
+
+### [5단계] 로그인 완료 (Session Creation)
+- **목적**: 받은 토큰을 검증하고, 브라우저가 인식할 수 있는 로컬 세션을 만듭니다.
+- **동작**:
+ 1. `jose` 라이브러리를 통해 `id_token`의 서명을 검증하고 payload(사번, 이름, 부서 등)를 추출합니다.
+ 2. 추출된 사용자 정보를 `express-session`의 `req.session.user`에 저장합니다.
+ 3. 클라이언트 브라우저에게 세션 쿠키를 발급하며 홈 화면(`/home.html`)으로 리다이렉트 시킵니다.
diff --git a/baron-sso_login_guide/headless-phone-login-flow.md b/baron-sso_login_guide/headless-phone-login-flow.md
new file mode 100644
index 0000000..27cb0e6
--- /dev/null
+++ b/baron-sso_login_guide/headless-phone-login-flow.md
@@ -0,0 +1,84 @@
+# Headless 전화번호 인증 로그인 로직
+
+이 문서는 사용자가 데모 애플리케이션에서 **전화번호**를 입력하여 인증 링크를 받고, 모바일에서 승인하여 로그인하는 내부 흐름을 설명합니다.
+
+## 핵심 개념
+
+- **Link Init**: 사용자의 전화번호로 실제 인증 링크(카카오톡 또는 SMS)를 발송하도록 SSO 서버에 요청하는 단계입니다.
+- **Polling**: 사용자가 모바일에서 링크를 클릭할 때까지 앱 서버가 주기적으로 SSO 서버에 "인증이 완료되었는지" 물어보는 과정입니다.
+- **Security**: 이 과정에서도 모든 API 호출은 RP의 Private Key로 서명된 `client_assertion`을 포함하여 보안을 유지합니다.
+
+---
+
+## 1. 전화번호 로그인 시퀀스 다이어그램
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor User as 사용자
+ participant RP as 데모 앱 (RP)
+ participant OIDC as Baron SSO (OIDC)
+ participant Auth as Baron SSO (Headless API)
+
+ User->>RP: 1. 전화번호 입력 후 인증 요청
+
+ note over RP: [1단계: 신호 요청]
+ RP->>OIDC: 2. Authorization Request (GET /oauth2/auth)
[login_challenge 획득]
+
+ note over RP: [2단계: 링크 발송 요청]
+ RP->>Auth: 3. 인증 링크 발송 요청 (POST .../link/init)
[client_assertion, login_challenge, 전화번호 포함]
+ Auth-->>User: 4. 인증 링크 발송 (카카오톡/SMS)
+ Auth-->>RP: 5. 대기 참조값(pendingRef) 반환
+
+ note over RP: [3단계: 인증 상태 폴링]
+ loop 인증 완료 시까지 반복 (최대 3분)
+ RP->>Auth: 6. 상태 확인 (POST .../link/poll)
[client_assertion, pendingRef 포함]
+ alt 아직 대기 중
+ Auth-->>RP: 7. authorization_pending 응답
+ RP->>RP: 잠시 대기 (interval)
+ else 사용자 링크 클릭 완료
+ Auth-->>RP: 8. 인증 성공 및 리다이렉트 URL 반환
+ end
+ end
+
+ note over User: 사용자가 모바일에서 링크 클릭 및 승인
+
+ note over RP: [4단계: 이후 과정 (사번 로그인과 동일)]
+ RP->>OIDC: 9. 리다이렉트 추적 및 Authorization Code 획득
+ RP->>OIDC: 10. Token Endpoint 호출 및 id_token 발급
+ RP->>RP: 11. 세션 생성 및 홈 화면 이동
+ RP-->>User: 12. 로그인 완료 안내
+```
+
+---
+
+## 2. 단계별 상세 로직 설명
+
+### [1단계] 신호 요청 (Login Challenge)
+- 사번 로그인과 동일하게 OIDC 표준 흐름을 시작하기 위해 `login_challenge`를 먼저 획득합니다. 이 값은 이후 인증 시도 시 "이 사용자가 어떤 OIDC 요청에 응답하고 있는지"를 SSO 서버에 알려주는 매개체가 됩니다.
+
+### [2단계] 링크 발송 요청 (Link Init)
+- **동작**: `POST /api/v1/auth/headless/link/init` 호출.
+- **데이터**: `client_assertion`, `login_challenge`, 사용자의 `loginId`(전화번호).
+- **결과**: SSO 서버는 사용자의 전화번호로 인증 가능한 고유 링크를 발송하고, RP에게는 해당 요청을 추적할 수 있는 `pendingRef`와 다음 폴링까지의 권장 대기 시간(`interval`)을 반환합니다.
+
+### [3단계] 인증 상태 폴링 (Polling)
+- **동작**: `POST /api/v1/auth/headless/link/poll`을 주기적으로 호출.
+- **상태 처리**:
+ - `authorization_pending`: 사용자가 아직 링크를 클릭하지 않았으므로 지정된 시간만큼 기다린 후 다시 시도합니다.
+ - `slow_down`: 폴링 간격이 너무 잦다는 신호로, 대기 시간을 조금 더 늘립니다.
+ - `expired_token`: 3분이 경과하여 인증 요청이 만료된 경우입니다.
+ - **성공**: 사용자가 승인을 완료하면 서버는 `redirectTo` 정보를 반환하며 폴링이 종료됩니다.
+
+### [4단계] 이후 과정 (Standard OIDC Flow)
+- 폴링 결과로 받은 `redirectTo` 주소부터는 표준 OIDC 흐름을 따릅니다.
+- 데모 앱은 해당 주소로 리다이렉트하며 발생하는 쿠키를 유지하고, 필요 시 사용자 동의(Consent) 과정을 자동 수행하여 최종적으로 `Authorization Code`를 얻어냅니다.
+- 마지막으로 해당 코드를 `id_token`으로 교환하여 사용자 정보를 세션에 저장합니다.
+
+---
+
+## 3. 특징 및 주의 사항
+
+- **비동기 사용자 경험**: 사용자는 PC에서 전화번호만 입력하고, 실제 인증 행위는 모바일에서 수행합니다. PC 화면은 폴링이 완료될 때까지 "인증 대기 중" 상태를 유지합니다.
+- **보안 검증**: 폴링 시에도 `client_assertion`이 필요합니다. 이는 제3자가 `pendingRef`를 가로채더라도 RP의 비밀키 없이는 인증 상태를 훔쳐볼 수 없음을 보장합니다.
+- **제한 시간**: 보안상 폴링은 보통 3분(180초)으로 제한되며, 이후에는 요청을 처음부터 다시 시작해야 합니다.
diff --git a/baron-sso_login_guide/setup-guide.md b/baron-sso_login_guide/setup-guide.md
new file mode 100644
index 0000000..521f3e3
--- /dev/null
+++ b/baron-sso_login_guide/setup-guide.md
@@ -0,0 +1,115 @@
+# Headless 로그인 데모 설정 가이드 (Baron SSO 연동)
+
+이 문서는 `headless-login-demo` 프로젝트를 설치하고, **Baron SSO (OIDC IdP)** 관리자 도구(`devfront`)에서 **Headless RP**를 올바르게 생성 및 설정하는 방법을 단계별로 설명합니다.
+
+---
+
+## 1. Baron SSO (devfront) 설정
+
+Headless RP는 일반 OIDC 클라이언트와 설정 방식이 다릅니다. 특히 **IdP 서버가 RP(데모 앱)의 JWKS 엔드포인트에 접속할 수 있어야 함**을 유의하십시오.
+
+### Step 1: 클라이언트 기본 정보 입력
+
+1. `devfront` 접속 후 **연동 앱 > 연동 앱 추가**를 클릭합니다.
+2. **Name**: `headless-login` (또는 자유롭게 입력)
+3. **Redirect URIs**: 데모 앱에 접속할 주소의 콜백 경로를 입력합니다.
+ - **통합 환경 (IdP와 RP가 같은 서버일 때)**: `http://localhost:3000/callback`
+ - **분리 환경 (IdP는 원격 서버, RP는 내 PC일 때)**: `http://[내_PC_IP]:3000/callback`
+ - _주의: 실제 앱에서 요청하는 Redirect URI와 여기서 등록한 값이 **완전히 일치**해야 인증 거부 에러가 발생하지 않습니다._
+4. **Scopes**: `openid`, `profile`, `email`을 선택합니다.
+5. **Type**: 반드시 `pkce`를 선택해야 합니다.
+
+
+
+### Step 2: Headless 기능 및 보안 설정
+
+1. `pkce` 하단의 **"Headless Login (자체 로그인 UI 사용)"** 토글을 활성화합니다.
+2. **JWKS URI**: **Baron SSO 서버에서 접근 가능한** 데모 앱의 공개키 주소를 입력합니다.
+ - **통합 환경 (IdP와 RP가 같은 서버일 때)**: `http://localhost:3000/.well-known/jwks.json`
+ - **분리 환경 (IdP는 원격 서버, RP는 내 PC일 때)**: `http://[내_PC_IP]:3000/.well-known/jwks.json`
+ - _주의: Baron SSO 서버(`172.16.10.175`)에서 사용자님의 로컬 PC 포트로 네트워크가 열려있어야 합니다._
+
+
+
+### Step 3: 저장 및 확인 (JWKS 캐시 검증)
+
+1. **앱 생성** 버튼을 클릭해 저장합니다.
+2. 연동 앱 목록에서 해당 앱이 **PKCE (Headless Login)** 유형으로 생성됐는지 확인합니다.
+3. 앱 상세 페이지 하단이나 설정 탭에서 **JWKS 캐시 상태**가 `Success`인지 반드시 확인합니다.
+ - _팁: 캐시 상태가 비어있거나 실패인 경우, 데모 앱(내 PC)이 켜져 있는지 확인하고 **새로고침(Refresh)** 버튼을 눌러 수동으로 캐시를 갱신하세요. 캐싱이 정상적으로 이루어져야만 로그인이 작동합니다._
+
+## 
+
+## 2. Headless Login 애플리케이션 로컬 설정 (.env)
+
+`devfront`에서 설정한 값을 바탕으로 프로젝트 루트의 `.env` 파일을 구성합니다.
+
+```env
+# 애플리케이션 실행 포트
+PORT=3000
+
+# OIDC IdP 설정 (원격 서버 주소 입력)
+CLIENT_ID=a9b64539-7242-4aa5-ad3d-13c7f1ef00f2
+ISSUER=http://172.16.10.175/oidc
+
+# 리다이렉트 및 보안 설정
+# REDIRECT_URI는 DevFront에 등록한 Redirect URIs 중 하나와 정확히 일치해야 합니다.
+REDIRECT_URI=http://[내_PC_IP]:3000/callback
+# JWKS_URI는 Baron SSO 서버가 내 PC로 접속할 때 사용하는 주소와 일치해야 합니다.
+JWKS_URI=http://[내_PC_IP]:3000/.well-known/jwks.json
+
+# tenant 제한 시 이동시킬 userfront 에러 경로
+ERROR_LOCALE_PATH=/ko/error
+```
+
+---
+
+## 3. 주의 사항 (네트워크 구성)
+
+- **서버 간 통신 (Server-to-Server)**: Headless 로그인은 Baron SSO 서버가 직접 데모 앱의 `JWKS_URI`에 접속하여 서명을 검증합니다. 따라서 IdP 서버에서 내 로컬 PC의 포트(`3000`)로의 인바운드 통신이 허용되어야 합니다.
+- **Redirect URI 일치**: 브라우저를 통해 접속할 주소가 IP라면, Redirect URI와 JWKS URI 모두 IP 기반 주소로 통일하는 것이 문제 발생 소지를 줄이는 가장 좋은 방법입니다.
+
+---
+
+## 4. 실행
+
+```bash
+npm install
+npm start
+```
+
+> **💡 참고: 자동 키 생성 및 JWKS 엔드포인트 활성화**
+> `npm start` 명령어로 서버를 실행하면, 프로젝트 내에 `keys.json` 파일이 자동으로 생성됩니다. 이 파일에는 서버가 자체적으로 발급한 RSA 보안 키 쌍(공개키/개인키)이 저장됩니다.
+> 동시에, `.env`에 설정된 `JWKS_URI` 경로(또는 기본 경로)로 공개키가 서빙되어 Baron SSO가 검증에 사용할 수 있게 됩니다.
+
+---
+
+## 5. Tenant 제한 테스트 가이드
+
+Headless RP는 login API 성공 이후 consent 단계에서 tenant 제한이 걸릴 수 있습니다. 따라서 단순히 `/api/v1/auth/headless/password/login` 성공만 보면 안 되고, 최종 redirect 해석까지 확인해야 합니다.
+
+### 권장 검증 순서
+
+1. 제한이 없는 상태에서 로그인 성공 여부를 먼저 확인합니다.
+2. `devfront`에서 대상 RP에 `tenant_access_restricted`와 `allowed_tenants`를 설정합니다.
+3. 허용된 tenant 사용자로 로그인해 정상 성공 여부를 확인합니다.
+4. 허용되지 않은 tenant 사용자로 로그인해 `userfront`의 `/ko/error?error=tenant_not_allowed...` 화면으로 이동하는지 확인합니다.
+
+### 기대 동작
+
+- `tenant_not_allowed`는 Baron SSO backend가 `403`으로 반환합니다.
+- headless demo는 이 응답을 감지해 `userfront` 에러 화면으로 브라우저를 이동시킵니다.
+- 따라서 브라우저 팝업으로 `Invalid URL`이 보인다면 demo 쪽 에러 처리 누락을 먼저 의심해야 합니다.
+
+### 로그 확인 포인트
+
+```bash
+docker logs --tail 100 headless-login-demo
+docker logs --tail 100 baron_backend
+```
+
+- `headless-login-demo`
+ - consent 단계에서 `tenant_not_allowed`를 받아 `errorUrl`로 변환했는지 확인
+- `baron_backend`
+ - `GET /api/v1/auth/consent` 또는 `POST /api/v1/auth/consent/accept`가 `403`인지 확인
+ - 해당 응답 body에 `code=tenant_not_allowed`가 포함되는지 확인
diff --git a/baron-sso_login_guide/setup-step1-example.png b/baron-sso_login_guide/setup-step1-example.png
new file mode 100644
index 0000000..a51da34
Binary files /dev/null and b/baron-sso_login_guide/setup-step1-example.png differ
diff --git a/baron-sso_login_guide/setup-step2-example.png b/baron-sso_login_guide/setup-step2-example.png
new file mode 100644
index 0000000..6f0e92c
Binary files /dev/null and b/baron-sso_login_guide/setup-step2-example.png differ
diff --git a/baron-sso_login_guide/setup-step3-example.png b/baron-sso_login_guide/setup-step3-example.png
new file mode 100644
index 0000000..d75179c
Binary files /dev/null and b/baron-sso_login_guide/setup-step3-example.png differ
diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml
index 539acdb..38910fd 100644
--- a/docker-compose.prod.yaml
+++ b/docker-compose.prod.yaml
@@ -40,7 +40,7 @@ services:
ports:
- "9090:80"
volumes:
- - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
+ - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./logs/nginx:/var/log/nginx
depends_on:
backend: