fix(dashboard): address persistent auth review

This commit is contained in:
2026-10-02 03:02:23 +00:00
parent 91e106d75c
commit 7bb959859a
11 changed files with 885 additions and 347 deletions
+3 -3
View File
@@ -47,9 +47,9 @@ cd /root/projects/jarca-ledger-mcp
uvicorn dashboard.server:app --host 0.0.0.0 --port 8501
```
인증 성공 시 Dashboard의 동일 ASGI 프로세스에 포함된 server-side 인증 endpoint가 `Secure`, `HttpOnly`, `SameSite=Lax`, `Path=/` 속성의 서명 cookie를 발급합니다. 기본 절대 만료는 24시간이며 `로그인 상태 유지 (30일)`을 선택하면 30일입니다. 일반 요청이나 재접속은 만료를 연장하지 않습니다. 관리자 password 또는 서명 secret을 교체하면 기존 cookie는 즉시 검증에 실패합니다. `로그아웃`은 browser cookie를 삭제하지만, 이미 탈취·복사된 stateless token을 서버에서 개별 폐기하지는 못하므로 사고 대응 시 password 또는 서명 secret을 교체해야 합니다.
인증 성공 시 Dashboard의 동일 ASGI 프로세스에 포함된 server-side 인증 endpoint가 `__Host-jarca_dashboard_auth` cookie를 발급합니다. Cookie는 `Secure`, `HttpOnly`, `SameSite=Lax`, `Path=/`, no `Domain`이며 token의 `sub`는 관리자 ID가 아닌 비민감 고정 role `dashboard-admin`입니다. 기본 절대 만료는 24시간이며 `로그인 상태 유지 (30일)`을 선택하면 30일입니다. 일반 요청이나 재접속은 만료를 연장하지 않습니다. 관리자 ID, password 또는 서명 secret을 교체하면 현재 설정에 묶인 서명 검증이 실패합니다. malformed·expired·tampered·rotation-invalid 또는 configuration-failure cookie는 보호 자원 전에 거부되고 same-origin `/api/auth/cleanup`에서 matching deletion 후 미인증 상태로 전이합니다. `로그아웃`도 browser cookie를 삭제하지만 stateless token을 서버에서 개별 폐기하지 않으므로 사고 대응 시 credential 또는 서명 secret을 교체해야 합니다.
`Secure` cookie를 사용하므로 browser가 접근하는 공개 origin은 HTTPS여야 하며 login/logout endpoint는 ASGI request scheme도 HTTPS가 아니면 거부합니다. TLS를 Ingress 또는 reverse proxy에서 종료할 때는 `JARCA_DASHBOARD_FORWARDED_ALLOW_IPS`를 실제 proxy source IP/CIDR allowlist로 설정해야 합니다. 기본값 `127.0.0.1`은 cluster ingress를 신뢰하지 않는 fail-closed 값입니다. `*` 또는 불특정 network를 신뢰하지 말고 proxy가 `Host`, `Origin`, `X-Forwarded-Proto`를 정확히 보존·설정하게 하세요. 인증 cookie의 발급·검증은 Dashboard 프로세스가 직접 수행합니다. 잘못된 ID 또는 password 응답은 매 제출마다 최소 1초 지연되지만 애플리케이션 잠금은 없습니다. 이 지연은 병렬 요청으로 우회할 수 있으므로 외부 노출 경계에 별도 rate limiting을 적용해야 합니다.
`Secure` cookie를 사용하므로 browser가 접근하는 공개 origin은 HTTPS여야 하며 login/logout endpoint는 ASGI request scheme도 HTTPS가 아니면 거부합니다. Login과 logout은 same-origin HTTPS POST만 허용하고 cleanup GET은 same-origin HTTPS `Referer`를 검증합니다. TLS를 Ingress 또는 reverse proxy에서 종료할 때는 `JARCA_DASHBOARD_FORWARDED_ALLOW_IPS`를 실제 proxy source IP/CIDR allowlist로 설정해야 합니다. 기본값 `127.0.0.1`은 cluster ingress를 신뢰하지 않는 fail-closed 값입니다. `*` 또는 불특정 network를 신뢰하지 말고 proxy가 `Host`, `Origin`, `Referer`, `X-Forwarded-Proto`를 정확히 보존·설정하게 하세요. 인증 cookie의 발급·검증은 Dashboard 프로세스가 직접 수행합니다. 잘못된 ID 또는 password 응답은 매 제출마다 최소 1초 지연되지만 애플리케이션 잠금은 없습니다. 이 지연은 병렬 요청으로 우회할 수 있으므로 외부 노출 경계에 별도 rate limiting을 적용해야 합니다.
이 로그인은 **Streamlit Dashboard만 보호하며 MCP endpoint를 인증하지 않습니다.** MCP는 별도 요구사항과 적절한 네트워크 경계로 보호해야 합니다.
@@ -129,4 +129,4 @@ Streamlit이 SQLite에 직접 접근하지 않고 MCP/API만 호출하도록 변
- 국민은행 PDF import는 암호화 PDF 비밀번호를 입력받아 PyMuPDF로 표를 추출하고, `transaction_datetime`, `counterparty`, `balance_after`, `branch`, `raw_summary`, `raw_payload`에 원본 세부 정보를 보존합니다.
- CSV/PDF/API import는 `import_batches`에 묶음 이력을 남기고, 잘못 가져온 batch는 `rollback_ledger_import_batch`로 되돌릴 수 있습니다.
- 카테고리에는 `cashflow_kind`를 저장해 실제 가계부 수입/지출(`income`, `expense`)과 계좌이체/투자이동/분석제외(`transfer`, `investment`, `exclude`, `debt_payment`, `unknown`)를 분리합니다.
- CSV import는 먼저 preview 후 저장하는 흐름으로 확장합니다.
- CSV import는 먼저 preview 후 저장하는 흐름으로 확장합니다.