You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> 쿠키 기반 인증을 사용하는 경우, 상태 변경 요청(POST/PUT/PATCH/DELETE)은 CSRF 방어(예: CSRF 토큰) 정책을 함께 적용하는 것을 권장합니다.
223
236
224
237
### 3. 비밀번호 분실 복구 프로세스
225
238
@@ -287,9 +300,9 @@ verifySession 메서드는 세션 ID로 세션을 조회한 후, 존재하지
287
300
288
301
**PIN 설정 엔드포인트(POST /setup-pin):** 먼저 요청자가 관리자 역할인지 확인합니다. PIN이 4~6자리 숫자인지 검증하고, 연속된 숫자(예: 1234)나 반복된 숫자(예: 1111)인지도 체크합니다. 검증을 통과하면 PIN을 해싱하여 해시값과 Salt를 콜론(:)으로 구분하여 데이터베이스에 저장합니다.
289
302
290
-
**PIN 인증 엔드포인트(POST /verify-pin):** 관리자 권한을 확인한 후, 저장된 PIN 해시를 조회합니다. 입력된 PIN과 저장된 해시를 비교하여 검증합니다. 실패하면 감사 로그를 남기고 401 에러를 반환합니다. 성공하면 30분 유효한 세션을 생성하여 세션 ID를 반환합니다.
291
-
292
-
**관리자 설정 접근 미들웨어(requireAdminPin):** 기본 인증과 관리자 권한을 먼저 확인합니다. 요청 헤더에서 관리자 세션 ID를 추출하고, 없으면 PIN 입력이 필요하다는 응답을 반환합니다. 세션 ID가 있으면 유효성을 검증하고, 만료된 경우에도 PIN 입력을 다시 요구합니다. 검증이 통과하면 다음 단계로 넘깁니다.
303
+
**PIN 인증 엔드포인트(POST /verify-pin):** 관리자 권한을 확인한 후, 저장된 PIN 해시를 조회합니다. 입력된 PIN과 저장된 해시를 비교하여 검증합니다. 실패하면 감사 로그를 남기고 401 에러를 반환합니다. 성공하면 30분 유효한 세션을 생성하고, `Set-Cookie`로 관리자 세션 쿠키(`admin_session`, `HttpOnly`)를 설정합니다. 프로덕션 환경에서는 `Secure`와 `SameSite=Strict`를 활성화합니다.
304
+
305
+
**관리자 설정 접근 미들웨어(requireAdminPin):** 기본 인증과 관리자 권한을 먼저 확인합니다. `httpOnly` 쿠키(`admin_session`)에서 관리자 세션 ID를 추출하고, 없으면 PIN 입력이 필요하다는 응답을 반환합니다. 세션 ID가 있으면 유효성을 검증하고, 만료된 경우에도 PIN 입력을 다시 요구합니다. 검증이 통과하면 다음 단계로 넘깁니다.
293
306
294
307
---
295
308
@@ -304,17 +317,17 @@ PinInput 컴포넌트는 사용자가 PIN을 입력하는 화면을 제공합니
304
317
305
318
각 자리마다 개별 입력란을 생성합니다. 숫자가 아닌 값은 입력할 수 없습니다. 숫자를 입력하면 자동으로 다음 입력란으로 포커스가 이동하고, Backspace를 누르면 이전 입력란으로 돌아갑니다. PIN의 모든 자리가 채워지면 onComplete 콜백을 실행하여 완성된 PIN을 전달합니다. 컴포넌트가 열리면 첫 번째 입력란에 자동으로 포커스됩니다. 에러 메시지가 있으면 입력란 아래에 빨간색으로 표시됩니다.
306
319
307
-
### PIN 인증 모달
320
+
### PIN 인증 모달
308
321
309
-
AdminPinModal 컴포넌트는 관리자 PIN 입력을 위한 팝업입니다. PinInput 컴포넌트를 내부에 포함시킵니다.
322
+
AdminPinModal 컴포넌트는 관리자 PIN 입력을 위한 팝업입니다. PinInput 컴포넌트를 내부에 포함시킵니다.
310
323
311
-
PIN 입력이 완료되면 백엔드의 /api/admin/verify-pin에 요청을 보냅니다. 응답이 성공하면 반환된 세션 ID를 sessionStorage에 저장하고 onSuccess 콜백을 실행합니다. 실패하면 'PIN이 올바르지 않습니다' 에러 메시지를 표시합니다. 요청 중에는 '인증 중...' 로딩 메시지가 표시됩니다. 모달 하단에는 이 인증은 30분간 유효하다는 안내가 표시됩니다.
ProtectedAdminRoute 컴포넌트는 관리자 전용 페이지를 보호하는 라우트 래퍼입니다.
316
-
317
-
컴포넌트가 마운트되면 먼저 기존 관리자 세션이 있는지 확인합니다. sessionStorage에 저장된 세션 ID가 없으면 바로 PIN 모달을 표시합니다. 세션 ID가 있으면 백엔드에 세션 유효성 검증을 요청합니다. 유효하면 자식 컴포넌트를 렌더링하고, 유효하지 않으면 sessionStorage의 세션을 삭제하고 PIN 모달을 다시 표시합니다. PIN 인증이 성공하면 verified 상태를 켜고 모달을 닫습니다. 관리자가 아닌 사용자는 홈 페이지로 리다이렉트됩니다.
328
+
ProtectedAdminRoute 컴포넌트는 관리자 전용 페이지를 보호하는 라우트 래퍼입니다.
329
+
330
+
컴포넌트가 마운트되면 먼저 백엔드에 관리자 세션 유효성 검증을 요청합니다(쿠키 기반). 유효하면 자식 컴포넌트를 렌더링하고, 유효하지 않으면 PIN 모달을 표시합니다. PIN 인증이 성공하면 verified 상태를 켜고 모달을 닫습니다. 관리자가 아닌 사용자는 홈 페이지로 리다이렉트됩니다.
318
331
319
332
---
320
333
@@ -345,15 +358,15 @@ logFailedAttempt 함수는 PIN 인증 실패 시 사용자 ID, 실패 액션, IP
345
358
346
359
GET /auth/google 엔드포인트는 사용자를 Google의 OAuth 인증 페이지로 리다이렉트합니다. 프로필과 이메일 정보에 대한 권한을 요청합니다.
347
360
348
-
GET /auth/callback 엔드포인트는 Google에서 돌아온 콜백을 처리합니다. 총 7단계로 진행됩니다. 첫째로 Google에서 반환된 Authorization Code를 Access Token으로 교환합니다. 둘째로 Access Token으로 사용자의 프로필 정보를 조회합니다. 셋째로 조회된 이메일이 Whitelist에 있는지 확인하고, 없으면 접근 거부합니다. 넷째로 사용자가 이미 존재하면 마지막 로그인 시간과 프로필 사진을 업데이트하고, 없으면 새로 생성합니다. 다섯째로 사용자 ID, 이메일, 역할로 JWT 토큰을 생성합니다. 여섯째로 생성된 토큰을 httpOnly Cookie로 저장하며, 프로덕션 환경에서는 secure 플래그도 활성화하고, 만료 시간은 7일로 설정합니다. 일곱째로 메인 화면으로 리다이렉트합니다.
361
+
GET /auth/callback 엔드포인트는 Google에서 돌아온 콜백을 처리합니다. 총 7단계로 진행됩니다. 첫째로 Google에서 반환된 Authorization Code를 Access Token으로 교환합니다. 둘째로 Access Token으로 사용자의 프로필 정보를 조회합니다. 셋째로 조회된 이메일이 Whitelist에 있는지 확인하고, 없으면 접근 거부합니다. 넷째로 사용자가 이미 존재하면 마지막 로그인 시간과 프로필 사진을 업데이트하고, 없으면 새로 생성합니다. 다섯째로 사용자 ID, 이메일, 역할로 JWT 토큰을 생성합니다. 여섯째로 생성된 토큰을 httpOnly Cookie로 저장하며, 프로덕션 환경에서는 secure 플래그도 활성화하고, 만료 시간은 Access Token 기본값(1일)로 설정합니다. 일곱째로 메인 화면으로 리다이렉트합니다.
349
362
350
363
---
351
364
352
-
## 로그인
353
-
354
-
**Backend:** POST /auth/logout 엔드포인트는 관리자인 경우 해당 사용자의 모든 관리자 세션을 삭제한 후, auth_token 쿠키를 삭제합니다.
365
+
## 로그아웃
355
366
356
-
**Frontend:** 로그아웃 버튼을 클릭하면 백엔드의 로그아웃 엔드포인트에 요청을 보냅니다. 완료되면 sessionStorage의 관리자 세션도 삭제하고, 로그인 페이지로 이동합니다.
367
+
**Backend:** POST /auth/logout 엔드포인트는 관리자인 경우 해당 사용자의 모든 관리자 세션을 삭제한 후, auth_token 쿠키와 admin_session 쿠키를 삭제합니다.
368
+
369
+
**Frontend:** 로그아웃 버튼을 클릭하면 백엔드의 로그아웃 엔드포인트에 요청을 보냅니다. 완료되면 로그인 페이지로 이동합니다.
0 commit comments