Files
jongryangje/docs/2차인증-TOTP-개발계획.md
2026-04-08 00:23:55 +09:00

5.3 KiB

2차 인증(TOTP) 개발 계획

종량제(쓰레기봉투 물류) 시스템 로그인에 시간 기반 일회용 암호(TOTP, RFC 6238) 를 도입하기 위한 계획서입니다.
웹 기능 목록(CSV)의 “로그인 2차 인증” 요구에 대응합니다.


1. 목표 및 범위

구분 내용
목표 아이디·비밀번호 이후 인증 앱(Google/Microsoft Authenticator 등) 6자리 코드로 2차 검증
범위 CodeIgniter 4 앱, session 기반 로그인(Auth), member 테이블
비범위(초기) SMS/이메일 OTP, WebAuthn, 공동인증서 연동

2. 정책(적용 대상)

  • 1차 권장: 관리자 계정만 TOTP 필수mb_level 지자체 관리자(3), super admin(4), 본부 관리자(5)
  • 일반 사용자(1)·지정판매소(2): 초기에는 미적용 또는 선택 적용 검토(지원 부담·UX)
  • 최종 정책은 보안/감사 요구에 맞춰 Roles 또는 설정으로 한 함수에 모아 판단 (needsTotpForMember() 등)

3. 사용자 흐름

3.1 로그인

  1. 기존과 동일: login_id, password, 승인 상태 검증
  2. TOTP 대상이고 시크릿이 등록됨(mb_totp_enabled = 1):
    • logged_in 세팅하지 않음
    • 세션에 pending_2fa, pending_mb_idx, (선택) 만료 시각만 저장
    • GET /login/two-factor 로 이동 → 6자리 입력 → 검증 성공 시 기존과 동일 세션 + mb_latestdate 갱신
  3. TOTP 대상인데 미등록:
    • 정책 A: 최초 로그인 시 시크릿 생성 + QR 표시 → 확인 코드 1회 검증 후 mb_totp_enabled = 1
    • 정책 B: 관리자가 수동으로 등록 유도(별도 화면)

3.2 로그아웃

  • pending_2fa 등 임시 키 반드시 제거

3.3 인증 앱

  • 표준 TOTP 앱이면 동일 시크릿으로 사용 가능(Google / Microsoft Authenticator 등)

4. 데이터베이스

member 테이블에 컬럼 추가(예시):

컬럼명 타입 설명
mb_totp_secret VARBINARY 또는 TEXT Base32 시크릿 — 저장 시 암호화 권장(encryption.key 등)
mb_totp_enabled TINYINT(1) 0=미사용, 1=등록 완료·로그인 시 검증 대상

선택:

  • mb_totp_enabled_at — 감사
  • 백업 코드 — 별도 테이블 또는 컬럼에 일회용 코드의 해시만 저장

DDL은 writable/database/member_add_totp.sql 등으로 관리 가능.


5. 기술 스택

  • TOTP 생성·검증: Composer 패키지 (예: spomky-labs/otphp 또는 robthree/twofactorauth)
  • QR(otpauth URI): 라이브러리 또는 URL 문자열만 표시 후 앱 수동 입력
  • 시크릿 보관: 평문 DB 저장 지양, CI Encrypter 또는 기존 PII 암호화 헬퍼와 동일 정책

6. 코드 변경 요약

영역 작업
app/Config/Routes.php login/two-factor GET·POST, (선택) setup 라우트
app/Controllers/Auth.php 로그인 분기, 2단계 검증 액션, 로그아웃 시 pending 제거
app/Models/MemberModel.php allowedFields 확장
신규 뷰 auth/login_two_factor.php, (선택) auth/totp_setup.php
app/Config/ (선택) Auth.php 또는 기존 설정에 requireTotp
app/Filters/ pending_2fa 상태에서는 보호 URL 접근 불가(원칙상 logged_in 없음으로 자연 차단, 허용 화이트리스트만 정리)
writable/database/*.sql 마이그레이션/ALTER

기존 MemberLogModel에 “2차 성공/실패” 구분 기록 여부 결정.


7. 개발 환경에서 2FA 생략

  • .env 예: auth.requireTotp = false (로컬만)
  • 운영/스테이징: true
  • 로직: 비밀번호 검증 성공needsTotp && config('Auth')->requireTotp 일 때만 2단계로 보냄
  • 운영에 false가 배포되지 않도록 CI·배포 체크리스트에 포함

8. 보안·운영

  • TOTP 검증 실패 횟수 제한 및 짧은 잠금(브루트포스 방지)
  • 시간 윈도우: 라이브러리 기본(예: ±1 step) 및 서버 NTP 권장
  • 기기 분실: 백업 코드 또는 관리자 시크릿 재발급(감사 로그) 절차
  • admin_selected_lg_idx 등 기존 세션은 2차 완료 후에만 의미 있게 유지

9. 테스트 시나리오(초안)

  1. TOTP 미등록 관리자 — 등록 플로우 후 로그인 성공
  2. TOTP 등록 관리자 — 잘못된 코드 거부, 올바른 코드 성공
  3. 일반 사용자 — 정책에 따라 2단계 생략 확인
  4. requireTotp = false — 개발 모드에서 1단계만으로 logged_in
  5. 로그아웃 — pending_2fa 잔존 없음

10. 구현 단계(제안)

단계 내용
Phase 1 DB 컬럼, 패키지, 시크릿 생성·저장·검증 유틸, 관리자만 TOTP 필수
Phase 2 등록 UI(QR), 백업 코드 또는 재설정 프로세스
Phase 3 일반 사용자 확대·정책 조정, 로그/감사 보강

11. 참고

  • 역할 상수: app/Config/Roles.php
  • 현재 로그인 완료 지점: app/Controllers/Auth.php (세션에 logged_in 설정)
  • 기존 내부 문서는 docs/ 에 둘 수 있으나 현재 .gitignore에 포함되어 저장소에는 올라가지 않음. 팀 저장소 공유용으로 본 파일은 documentation/ 에 둠.