Skip to content

feat: Apple 로그인과 서버 사용량 제한 도입 - #6

Open
hyesngy wants to merge 2 commits into
developfrom
fix/security-critical-high-apple-login
Open

hyesngy wants to merge 2 commits into
developfrom
fix/security-critical-high-apple-login

Conversation

@hyesngy

@hyesngy hyesngy commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

작업 내용

공유 토큰과 로컬 UUID에 의존하던 인증·사용량 판정을 Apple 로그인, StoreKit 검증, Redis 기반 서버 권한으로 전환한다.

  • Apple 로그인 challenge, 세션 발급·갱신·로그아웃·계정 삭제 API 추가
  • Apple identity token과 StoreKit/App Store 구독 상태를 서버에서 검증
  • 무료 3회, Pro 100회 일일 한도를 Redis에서 원자적으로 강제
  • Gemini 요청 형식·이미지·모델·출력 토큰을 서버에서 제한
  • Release API 주소 고정, 공유 Scheme의 StoreKit 테스트 설정 제거
  • 3일 무료 체험과 일일 100회 정책에 맞춰 StoreKit·Paywall 문구 정리
  • Debug 기본 프록시를 https://preview-api.paxo.co.kr로 분리
  • 개인정보 처리방침과 운영 문서, CI 시크릿 검사 및 프록시 테스트 정비
  • 유지되지 않는 Cloudflare Worker 프록시 제거

변경 및 영향 범위

  • 앱 기능 (Capture / AI / Storage / UI)
  • StoreKit·사용량 정책
  • API·프록시
  • 앱 설정·권한·릴리스
  • 테스트·CI·개발 도구
  • 규칙·문서 (AGENTS.md, docs/)
  • 기타:

사전 식별 리스크

  • Vercel Production과 Preview에 Apple 로그인, App Store, Redis 관련 Sensitive 환경변수가 모두 등록돼야 한다.
  • Preview는 SANDBOX와 paxo:preview, Production은 PRODUCTION과 paxo:prod 조합만 허용한다.
  • App Store Connect 구독 상품과 Sandbox 계정은 코드 외부에서 별도로 준비해야 한다.
  • Apple 로그인 entitlement 변경 후 실제 배포 서명용 프로비저닝 상태를 확인해야 한다.
  • preview-api.paxo.co.kr은 가비아 DNS에 A 76.76.21.21 레코드가 필요하다.

결과 및 검증

기대 효과

  • 공유 앱 토큰이나 임의 UUID만으로 Gemini 호출 권한을 얻을 수 없다.
  • 서버 장애나 Redis 확인 실패 시 Gemini를 호출하지 않는다.
  • 무료·Pro 사용량과 구독 권한이 앱 재실행 및 서버 인스턴스 변경 후에도 유지된다.
  • 동일 풀이의 중복 요청과 갱신 토큰 동시 재사용을 차단한다.

실제 반영 결과

  • 앱은 Apple 로그인 완료 후 15분 액세스 세션과 회전식 갱신 토큰을 사용한다.
  • 원본 Apple 식별자는 저장하지 않고 HMAC subject만 사용하며, Apple 갱신 토큰은 AES-256-GCM으로 암호화한다.
  • 성공한 정답만 일일 사용량으로 확정하고, 동일 solveId의 해설 1회는 추가 차감하지 않는다.
  • Release 빌드는 https://api.paxo.co.kr만 사용하며 직접 Gemini 호출과 프록시 변경은 DEBUG로 제한한다.
  • Debug 빌드는 비어 있는 프록시 설정에서 https://preview-api.paxo.co.kr을 사용한다.
  • 무료 체험 기간은 StoreKit 상품에서 읽고, 실제 최초 혜택 대상에게만 표시한다.
  • 기존 ToastController의 actor 격리 경고는 이번 Critical/High 범위 밖으로 유지한다.

자동 검증

  • npm test: 프록시 단위 테스트 32개 통과
  • npm run check: JavaScript 문법 검사 통과
  • xcrun swift-format lint --recursive --strict Paxo PaxoTests: 통과
  • xcodebuild Debug test: Swift 테스트 24개 통과
  • xcodebuild Release build: arm64/x86_64 범용 빌드 통과
  • Release 바이너리에 Preview URL이 없고 운영 URL만 포함됨을 확인
  • git diff --check, StoreKit JSON 파싱 및 알려진 시크릿 패턴 검사 통과
  • GitHub Actions 4개 작업 통과

Vercel Preview 검증

  • Preview 배포: https://paxo-proxy-d5eljgwdf-paxo.vercel.app
  • 배포 상태: READY, Node.js Functions 7개 생성
  • /privacy: 200
  • 앱 토큰 없는 /session/challenge, /generate: 401
  • 정상 앱 토큰의 /session/challenge: 200 및 Redis nonce 저장 성공
  • 정상 앱 토큰 + 잘못된 세션의 /generate: Gemini 호출 전 401
  • preview-api.paxo.co.kr 공용 DNS와 HTTPS 연결 확인, /privacy: 200
  • 런타임 로그에 토큰·프롬프트·이미지·Apple 식별자가 기록되지 않음을 확인
  • Preview 전용 Firewall rate-limit 2개를 429 차단 모드로 게시함
  • 두 규칙 모두 Preview 환경에만 적용되며 active/valid 상태, 남은 Firewall 초안 없음
  • Firewall 실측: /session/challenge는 401 10건 후 429 2건, /generate는 401 60건 후 429 5건
  • Vercel Traffic에서 Rate Limited 7건 집계 확인
  • Apple 로그인 후 POST /session 200 및 free tier 세션 발급 확인

App Store Connect 설정

  • Paxo Pro 그룹에 월간·연간 상품을 동일 구독 수준으로 등록
  • 월간: 미국 기준 $4.99, 연간: 미국 기준 $39.99
  • 두 상품 모두 175개 국가 또는 지역 판매 및 최초 3일 무료 체험 등록
  • 월간·연간과 구독 그룹의 한국어·영어 표시 정보 등록
  • Billing Grace Period 비활성 상태 확인
  • 심사 제출과 실제 결제는 수행하지 않음

남은 외부 검증

  • 가비아 DNS에 preview-api A 레코드 추가 후 Vercel 별칭·HTTPS 확인
  • App Store Connect에 월간·연간 자동 갱신 구독과 3일 체험 생성
  • Sandbox Apple Account로 Apple 로그인 및 free tier 세션 발급 확인
  • 무료 정답 3회, 해설, 4번째 캡처 전 차단 검증
  • 월간/연간 구매·복원·만료 검증(유료 앱 계약 활성화 후)
  • Preview Firewall 429 차단 모드 전환 및 제한 동작 확인

리스크·결정·리뷰

  • 일반 변경
  • Critical Path 변경

트러블슈팅 및 회고

  • 앱과 서버 양쪽에서 갱신 요청을 직렬화하고 Redis에서 갱신 토큰을 원자적으로 소비해 동시 재사용 경합을 제거했다.
  • AppTransaction을 사용할 수 없는 macOS 14에서는 검증된 구독 Transaction을 서버에 전달하는 폴백을 적용했다.
  • Vercel 프로젝트는 Git 저장소에 연결돼 있지 않아 develop 병합으로 자동 Production 배포가 발생하지 않는다.
  • Production 배포는 이번 작업 범위에서 수행하지 않는다.

메모

  • Sandbox 구매·복원 E2E 검증을 완료하기 전에는 PR을 병합하지 않는다.

- Apple 로그인 및 StoreKit 기반 서버 권한 검증 추가
- Redis 기반 무료·Pro 일일 한도와 동시 요청 제어 적용
- 세션 갱신·로그아웃·계정 삭제 및 보안 테스트 추가
- Release 프록시 고정과 개인정보 처리방침·배포 문서 정비
- StoreKit 무료 체험을 3일로 맞추고 한국어·영어 상품 설명을 추가

- 실제 최초 혜택 대상에게만 무료 체험을 표시

- Debug 빌드 기본 프록시를 Preview 도메인으로 분리

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant