App Store Connect API 401:2026 JWT どう直す?

App Store Connect API 401が出たら、鍵を何度も撤回して作り直すのではなく、まず呼び出し先を確認し、鍵の用途、JWT、時刻、権限、リモートMacの資格情報注入の順に切り分けてください。最小の読み取りリクエストでも401が続く場合は、リクエストIDを添えてAppleへ問い合わせるのが最短です。

この手順は、fastlaneでTestFlightへアップロードする独立開発者、公開処理をリモートMacへ移したあとにローカル成功・CI失敗となった保守担当者、自分でJWTを発行してApp Store Connect APIを呼び出す開発者向けです。

401の発生地点

最初に確認するのは、JWTを作れたかではなく、そのJWTをどの処理へ送ったかです。App Store Connect API、App Store Server API、Transporterによるアップロード、fastlaneの各アクションは、似た公開処理の中にあっても同じ認証経路とは限りません。

ログには、秘密情報を残さない範囲で次の情報を記録します。

  • リクエスト先のホスト名とパス
  • HTTPステータスとAppleのエラーコード
  • リクエストID
  • 実行したfastlaneアクション、スクリプト、Runner名
  • ローカル、SSH、CIのどの入口から実行したか
  • TestFlight送信前のJWT認証なのか、アップロード処理中なのか

AppleのApp Store Connect APIエラー応答の説明では、ステータスだけでなくエラー応答の内容を使って原因を判断する前提になっています。401という数字だけを見て、すぐに権限不足やApple側の障害と決めつけないでください。

鍵の用途とAPI境界

App Store Connect API用の鍵は、AppleのApp Store Connect側で発行したものかを確認します。In-App Purchaseなど別のサービス入口で作成した鍵は、拡張子が同じ.p8でも、App Store Connect APIの呼び出しに使えるとは限りません。

確認する根拠は、ファイル名ではなく次の3点です。

  • App Store Connectの鍵一覧に表示される用途
  • Apple側に表示されるKey ID
  • JWTを送信している実際のAPIエンドポイント

App Store Connect APIの公式案内にある鍵の発行場所と、手元の設定を照合してください。チーム用の鍵か個人用の鍵かだけで結論を出すのではなく、今回の処理に必要な操作と鍵のロールが一致しているかを確認する必要があります。

ここで鍵を撤回する場合は、先に代替鍵で最小リクエストを検証します。既存のCI、リモートMac、手元のスクリプトが同じ鍵を使っている可能性があるため、検証前の撤回は、原因を増やしたうえで復旧経路まで失う操作になり得ます。

JWTの入力値とシステム時刻

App Store Connect APIのJWTは、署名できることだけでなく、Header、Payload、署名に使った秘密鍵が一つの組として正しい必要があります。AppleのJWT生成要件に沿って、次を照合します。

  • HeaderのalgES256になっているか
  • HeaderのkidがApple側のKey IDと一致しているか
  • PayloadのissがIssuer IDと一致しているか
  • audがApp Store Connect API向けの値になっているか
  • iatexpが現在時刻に対して妥当か
  • 署名に使った.p8が、そのKey IDに対応しているか

公式要件では、トークンの有効期間は最大20分です。AppleのJWT生成ドキュメントにある時間条件を基準にし、手動で値を延長するのではなく、発行直前の時刻から生成してください。

リモートMacでは、休止状態からの復帰、仮想ディスクのスナップショット復元、手動設定された時刻、時刻同期サービスの状態がローカルと異なることがあります。ローカルでJWTデコーダーが署名を検証できても、Appleが見るiatexpが現在時刻から外れていれば拒否されます。JWT全体や秘密鍵をログへ出力せず、時刻、Key ID、Issuer IDの一部だけをマスキングして比較します。

ロールとアクセス範囲

JWTの形式が正しくても、鍵に付与されたロールが目的の操作を許可していなければ、認証済みの後段で拒否されることがあります。一方、エンドポイント、鍵の用途、署名が合っていない場合は、権限設定だけを変えても401は直りません。

App Store ConnectのUsers and Access、Integrations、対象アプリのアクセス範囲を分けて確認してください。Appleのロールと権限一覧を見ながら、次の順に狭く検証します。

  • APIアクセスがチーム側で有効になっているか
  • 使用中の鍵に必要なロールがあるか
  • 対象アプリが鍵のアクセス範囲から外れていないか
  • 契約、チーム状態、ユーザー状態に未解決の問題がないか
  • 読み取りだけの最小APIリクエストが通るか

読み取りリクエストが成功しても、TestFlightへのアップロード権限やfastlaneの後続処理まで成功するとは限りません。逆に、最小リクエスト自体が401なら、ビルド、署名、ipaの内容を調べる前に認証層へ戻るべきです。

fastlaneとリモートMacの注入経路

fastlaneを使う場合、設定ファイルに書いた値ではなく、実行時にfastlaneが読み込んだ値を確認します。fastlaneのApp Store Connect API設定に合わせ、key_idissuer_idkey_filepathkey_contentのどの方式を採用しているかを固定してください。

ローカル端末で成功し、リモートMacのSSHやCI Runnerで失敗する場合は、次の差分を比較します。

  • ログインシェルと非対話シェルで環境変数が同じか
  • CIのシークレットがジョブへ渡されているか
  • Base64から.p8へ戻す際に改行が壊れていないか
  • key_filepathの作業ディレクトリが実行入口ごとに変わっていないか
  • fastlaneが別のLaneや別の設定ファイルを読んでいないか
  • API認証用の.p8とコード署名用の証明書を混同していないか

秘密鍵はソースリポジトリ、ビルド成果物、通常のログへ置かないでください。脱​​敏したKey ID、Issuer ID、ファイルの存在確認、JWTのHeaderとPayloadの非秘密部分だけを診断材料にし、秘密鍵そのものは出力しません。

リモートMacを継続的な公開処理に使う場合は、KVMFLUXのMac利用シーンも確認しながら、実行環境の保管場所、SSH接続、ログの保持方針を先に決めておくと、ローカルとの差分を追いやすくなります。

復旧判定のチェックリスト

次の項目を上から順に実行してください。途中で最小リクエストが成功したら、成功した層を記録してから次のTestFlight処理へ進みます。

  • [ ] リクエスト先がApp Store Connect APIか、別のApple APIやTransporter処理かを記録する
  • [ ] HTTPステータス、Appleのエラーコード、リクエストID、実行ツールを保存する
  • [ ] 鍵の発行場所、Key ID、Issuer IDをApple側の表示と照合する
  • [ ] ES256kidissaudiatexpと署名用.p8を照合する
  • [ ] ローカル端末とリモートMacの時刻、タイムゾーン、時刻同期状態を比較する
  • [ ] 鍵のロール、対象アプリの範囲、チームの契約・ユーザー状態を確認する
  • [ ] SSHとCI Runnerで、実際に読み込まれた設定方式とファイルパスを確認する
  • [ ] 秘密鍵、JWT全体、App ID、Bundle ID、ホスト名をログから除去する
  • [ ] 権限が許す最小の読み取りリクエストを実行する
  • [ ] 成功後にTestFlightへの実アップロードを行い、認証と転送を別々に記録する
  • [ ] 新しい鍵を作る場合は、代替鍵の検証後に旧鍵を撤回する
  • [ ] 複数環境で最小リクエストが失敗する場合は、リクエストID付きでAppleへ相談する

よくある認証の切り分け

JWTを生成できても成功とは限らない理由

JWTライブラリがトークンを生成し、ローカルの署名検証も通ったとしても、それは「秘密鍵で構文と署名を作れた」という意味にとどまります。Appleが確認する鍵の用途、送信先、Issuer ID、Audience、時間、ロールまで一致して初めて、APIリクエストの認証条件がそろいます。

fastlaneのTestFlight処理だけが失敗する場合

最小APIリクエストが成功し、TestFlight処理だけ失敗するなら、JWTだけでなくfastlaneのアクション、アップロード用資格情報、アプリへのアクセス範囲を分けて調べます。ビルド署名の問題をAPI 401の原因として扱わず、どの段階でAppleから拒否されたかをログで確認します。

App Store Connect API鍵と別サービス鍵を混同した場合

同じ.p8という見た目でも、発行元の画面と認可範囲が違えば代替にはなりません。ファイル名を変更したりJWTのPayloadを調整したりする前に、Apple側の鍵一覧で用途を確認し、対象エンドポイントに対応した鍵を使ってください。

ローカル成功・リモート失敗の場合

この場合は、アカウント全体の問題と決める前に、環境変数のスコープ、改行、作業ディレクトリ、時刻、読み込まれた設定ファイルを比較します。ローカルと同じ秘密情報を渡したつもりでも、CIではシークレットが未注入、空文字、別の改行形式になっていることがあります。

現在の環境とリモートMacの判断

ローカルのMacだけで公開処理を続ける構成は、端末の電源状態、ログインセッション、手動更新、開発者本人の作業時間に依存します。WindowsやLinuxから一時的にMacへ接続する構成では、認証情報の受け渡し、時刻差、SSHと対話型ターミナルの環境差も増えます。

一方、リモートMacを常駐の公開環境として使えば、fastlaneの設定、ログ、Runnerの状態を同じホストで管理しやすくなります。ただし、長期運用では鍵のローテーション、アクセス権、秘密情報の保管、実アップロードによる検証を自分で設計する必要があります。まずはリモートMacのよくある質問で接続方式と運用条件を確認し、短期の検証か常駐の公開機かを分けて判断してください。

手元のMacが故障中、CIを数日だけ再現したい、チームで同じmacOS環境を維持したいという状況なら、KVMFLUXのMacレンタルを一時的な検証環境として比較できます。自前のMacは購入費用だけでなく、常時稼働、保守、ストレージ、遠隔接続の準備が必要ですが、レンタルなら期間を区切って実アップロードまで試せます。逆に、物理ポートが必要な開発や、長期間にわたり高負荷処理を固定運用する場合は、自前機のほうが管理しやすい可能性があります。

ローカルとリモートMacの最小リクエストを比較し、実際のTestFlight送信まで確認できた段階で、週単位の検証にするか、月単位の常駐公開機にするかを決めてください。条件が合う場合は、KVMFLUXの料金案内で利用期間と運用形態を確認できます。

よくある質問

App Store Connect APIが401 NOT_AUTHORIZEDを返すとき、最初に見る場所はどこですか?

まず実際のエンドポイントがApp Store Connect APIか、別のApple APIやTransporter処理かを確認します。そのうえでレスポンスのエラーコード、リクエストID、実行したツールを保存し、同じ最小リクエストをローカルとリモートMacで比較してください。JWTを生成できた事実だけでは、対象APIの認証成功とは判断できません。

JWTをローカルで検証できるのにAppleで拒否されるのはなぜですか?

署名の検証と、Appleが要求する鍵の用途、issuer、audience、時刻、権限の検証は別の段階です。形式が正しくても、別サービス用の.p8、異なるKey ID、期限切れのexp、時刻がずれた実行環境で発行したトークンなら拒否されます。署名入力と実際の送信先を分けて確認します。

fastlaneでAPIキーを使ってTestFlightへ送れない場合、何を比較すべきですか?

fastlaneが実際に読み込んだkey_id、issuer_id、key_filepathまたはkey_contentを、対話型シェル、SSH、CI Runnerごとに比較します。環境変数のスコープ、改行、Base64復元、作業ディレクトリが異なると、同じ設定名でも別の値が渡されます。コード署名用証明書とAPI認証用.p8も混同しないでください。

App Store Connect API用の鍵とIn-App Purchase用の鍵は共用できますか?

同じ.p8形式でも、発行された入口と認可範囲が同じとは限りません。ファイル名や保存場所では用途を判断せず、Apple側の鍵一覧、Key ID、呼び出し先エンドポイントを照合してください。対象APIに対応しない鍵を使っている場合、JWTの見た目を修正しても認証は成功しません。

CI/CDの認証検証に、KVMFLUXのリモートMacを

JWT認証やアプリのビルド作業を、安定したリモートMac上で継続的に検証できます。 ローカル環境と分離した実行環境を用意し、認証情報や権限に関する問題を切り分けやすくします。 必要な期間だけMac環境を利用できるため、設備投資を抑えながら開発と配布の検証を進められます。 CI運用やアプリ開発に適したMac環境をお探しなら、KVMFLUXのMacレンタルをご検討ください。

Mac Mini M4 · 16GB / 256GB
日額$19.3 /日
週額$52.2 /週
月額$96.7 /月
四半期$263 /期