Zettelkasten

Play Console SA는 앱 권한만으로는 purchases.subscriptions.get이 401을 반환한다

·수정 3

요약

  • Google Play Console에서 SA에 앱 권한(App permissions) 만 부여하면 inappproducts.get, voidedpurchases.list 같은 호출은 되지만 purchases.subscriptions.get (v1/v2 모두) 은 401 permissionDenied로 실패한다.
  • 계정 권한(Account permissions) 까지 동일 항목으로 추가 부여해야 모든 androidpublisher 엔드포인트가 동작한다.
  • 같은 "재무 데이터 보기" 권한이라도 App 레벨과 Account 레벨이 별개 스코프로 평가된다.

본문

사건 요약

AWS Secrets Manager로 SA JSON을 옮긴 PR이 머지된 시각과 Sentry 에러 발생 시작 시각이 거의 일치하여 마이그레이션 버그로 의심했으나, secret의 private_key_id가 기존 파일명과 동일했다. 같은 SA, 같은 키였으므로 마이그레이션은 무관하고 Play Console 권한 자체가 누락된 케이스였다.

권한 별 동작 매트릭스

같은 SA에 대해 endpoint별로 응답이 다르게 나온다:

Endpoint 앱 권한만 앱 + 계정 권한 필요 권한
inappproducts.get ✅ 200 ✅ 200 View app info
monetization.subscriptions.list ✅ 200 ✅ 200 View app info
purchases.voidedpurchases.list ✅ 200 ✅ 200 View financial (App level OK)
purchases.subscriptions.get v1 ❌ 401 ✅ 200 View financial (Account level 필요)
purchases.subscriptionsv2.get ❌ 401 ✅ 200 View financial (Account level 필요)

같은 "View financial data"인데 voidedpurchases.list는 앱 권한으로 통과하고 subscriptions.get은 통과 안 한다. Google 내부 권한 평가 모델이 endpoint별로 다른 스코프를 본다는 의미다.

진단 시 함정 — fake token으로 false 401

권한 검증 목적으로 가짜 토큰을 넣어 purchases.subscriptions.get을 호출하면 Google이 token enumeration 방어 차원에서 invalid token에 대해서도 401 "insufficient permissions" 를 반환할 수 있다. 따라서 권한 OK/NG 판정은 다음 중 하나로 검증해야 신뢰 가능:

  • voidedpurchases.list 처럼 입력 없이 호출 가능한 list 호출의 응답
  • production RTDN 콜백의 real token이 들어온 결과(Sentry)

권한 부여 체크리스트

androidpublisher SA 신규 등록 / 회전 시:

  1. Play Console → Users and permissions → 해당 SA 클릭
  2. 앱 권한 탭에서 대상 앱(com.example.app) 추가 + 권한 체크
    • 재무 데이터 보기
    • 주문 및 구독 관리
  3. 계정 권한 탭에서도 동일 권한 체크 ← 이 단계 누락이 본 사건의 원인
  4. 매트릭스 테스트 스크립트로 purchases.subscriptions.get 포함 6개 endpoint 검증

흔히 놓치는 사실

  • secret 회전만으로는 권한이 따라오지 않지만, 같은 SA를 새 등록처럼 재등록한 경우에는 권한이 새로 부여돼야 한다.
  • Play Console의 "Setup → API access" 메뉴는 이미 deprecated된 계정이 많아서 거기 없다고 해서 잘못된 게 아니다. 통합 권한 모델(Users and permissions)이 표준이다.
  • 권한 부여 후 propagation은 endpoint별로 시간차가 있어 intermittent 401/400이 관측될 수 있다.

관련 노트

참고