5.3 KiB
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 로그인
- 기존과 동일:
login_id,password, 승인 상태 검증 - TOTP 대상이고 시크릿이 등록됨(
mb_totp_enabled = 1):logged_in세팅하지 않음- 세션에
pending_2fa,pending_mb_idx, (선택) 만료 시각만 저장 GET /login/two-factor로 이동 → 6자리 입력 → 검증 성공 시 기존과 동일 세션 +mb_latestdate갱신
- TOTP 대상인데 미등록:
- 정책 A: 최초 로그인 시 시크릿 생성 + QR 표시 → 확인 코드 1회 검증 후
mb_totp_enabled = 1 - 정책 B: 관리자가 수동으로 등록 유도(별도 화면)
- 정책 A: 최초 로그인 시 시크릿 생성 + QR 표시 → 확인 코드 1회 검증 후
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. 테스트 시나리오(초안)
- TOTP 미등록 관리자 — 등록 플로우 후 로그인 성공
- TOTP 등록 관리자 — 잘못된 코드 거부, 올바른 코드 성공
- 일반 사용자 — 정책에 따라 2단계 생략 확인
requireTotp = false— 개발 모드에서 1단계만으로logged_in- 로그아웃 —
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/에 둠.