RM-BLOG

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

Instagram Graph APIが突然死した件 - 2022/09/21

はじめに

タイトルのとおりだが、これは前回ブログにしたこっちの件とは別件である。ちなみに、とりあえずエラーが起きないようにはなったものの、現時点で完全に原因がわかったわけではない(なぜ動くようになったのかはハッキリとはわかってない)ので、また起きるかもしれない。とりあえず遭遇したエラー内容や実施した調査、対処などを備忘録としてまとめておく。

事象

2022/09/21 12:40UTCの回からInstagram Graph APIが突然400エラーを吐き始めた。

{"message":"Request failed with status code 400","name":"AxiosError","config":{"transitional":{"silentJSONParsing":true,"forcedJSONParsing":true,"clarifyTimeoutError":false},"transformRequest":[null],"transformResponse":[null],"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"maxBodyLength":-1,"env":{},"headers":{"Accept":"application/json, text/plain, /","User-Agent":"axios/0.27.2"},"method":"get","baseURL":"https://graph.facebook.com/","params":{"limit":"5","fields":"id,caption,media_type,media_url,children{id,media_url,media_type},permalink,timestamp","access_token":"xxx..."},"url":"111/media"},"code":"ERR_BAD_REQUEST","status":400}

最初の2~3回は「まあたまに起きるからな」程度で済ませていたが、1時間経過しても改善しないため、なんかおかしいかもしれんと思うに至った。取り急ぎ以下の観点の調査を実施。しかしこの時点で原因は不明だった

  • 前回同様、何かのAlertの対応を実施していないのではないかと疑いMeta Developer Siteにアクセスしたが、特にAlertが来ている様子はなかった。
  • Instagram Graph APIの障害を疑ったが、Twitterに呟きなし。DownDetectorにも目立った特徴はなかった。ちなみにこのときInstagram Graph APIStatus Siteがあることを初めて知った。そしてここにも特に障害情報なし。つまりInstagram Graph API自体は正常に動作している。
  • しかしInstagram Graph APIは利用人口が極端に少ないせいか、障害と思しき現象に遭遇した時、それをTwitterで検索するのは向いてない、というより実質無理。検索しても半分くらい俺のボヤキがひっかかるのがその無理さを物語っている。あとは数年前のつぶやきだったりとか。AWSくらいの規模の障害だったらTwitterが実質一番最速だったりするが、Instagram Graph APIは無理だ。もっとみんな使ってほしい(他力本願)

調査1

POSTMANでリクエスト送ってみたら以下のようなレスポンスが返ってきた

{
    "error": {
        "message": "(#10) Application does not have permission for this action",
        "type": "OAuthException",
        "code": 10,
        "fbtrace_id": "Axxxxxxxxxxxxxxx-Txxxxx"
    }
}

ん??Permissionがない??んな馬鹿な…と思いながらも、ひょっとしてInstagramが必要になるPermission変えたとか??と思って念のためメディアAPIのドキュメントを調べたところ以下の記述を発見。

ふむ、記憶と照らし合わせても別にそこまで強い違和感はない。しかし一応念のためこの必要Permissionはメモっておく。
続いてこのPermissionをちゃんと持っているのかというのをDeveloper Siteで確認。
すると今までと違いPermissionの管理画面が全然変わっていたことに(今更)気付く。

野郎ッ!Permissionの管理方法を知らない間に変えやがったのかッ! ...とこの時点では「Instagramが勝手に(予告なく)Permissionの管理仕様を変えたため」というのが原因だと疑ってしまったが。
結論からいうとここに原因はなかった(と思われる)。
この画面の見え方が現時点でもはっきりわかってないのでもしかしたらここにも少なからず原因がある可能性はあるが、この画面のガイダンスの記述を見る限り、「Standard Access」はアプリレビュー(Facebookの審査)なしで保有できる。そして、メディアAPIで必要となるinstagram_basicpages_read_engagementpages_show_listはこの画面見る限りではStandard Access保有済みだった。(見方が間違ってなければ)例えば以下はinstagram_basicの権限欄の表示内容である。

最初はこの画面の見方がわからず、「アドバンセスアクセスをリクエスト」しちゃいかけたのだが、これをやろうとする場合、Facebookにマジモンのアプリ審査を依頼することになる。「マジモンのアプリ審査」というのは、どんな目的で使うのかを説明したり、エンドユーザーの利用イメージを動画で撮ってアップロードしたり、その他諸々である。なんだこのクソ面倒くせえのは、こんなことまでしなきゃいけねえくらいならもうInstagram Graph APIなんて使うの辞めるぜとサウザーのような心持ちにすらなったが、さすがにここまでしなきゃいけないのはなんかちょっとおかしい気がするとふと我に返り、一旦リクエストの申請は取りやめて別の方向の調査に着手した。

調査2

ふとグラフAPIエクスプローラーを開いて実行してみたところ、普通にレスポンスが返ってきた。あれ?と思ったが、まさかと思いそのとき使っていたトークンを使い、手元の開発環境の設定を更新してみたところ、正常に動作した。
なんとここまできてトークンの有効期限切れとかいう超初歩の問題にぶちあたったのかと、げんなりしたのだが、調べてみるとちょっとそれとは性質が違っていたらしい。

なお、グラフAPIエクスプローラーで発行されるアクセストークンは、検証のための一時的なもの、いわゆる「第一アクセストークン」というやつで、有効期限が1時間程度しかない超短命のアクセストークンである。
このため、常駐型のツール等で利用する場合は、有効期限がもっと長い(俺が当時調べたときは「原則無期限」だったはず)「第三アクセストークン」というのを発行して利用するのが一般的(?)である。
かくいう俺も今まで、調べたら発行したの約3年前らしいんだがw、この「第三アクセストークン」というのを発行して使い続けていたのだが、上述したとおり、第三アクセストークンは少なくとも有効期限に問題はないはずだし、実際エラーメッセージにもその旨は指摘されていない。なぜトークンの再発行で改善したのか?

「アクセストークンデバッガー」で調べた。左側がもともと使ってたアクセストークン、右側が今回新たに発行した(期限は短いが)アクセストークン。

見比べてみると違いは「タイプ」の項目の内容だけのようだ。なお、両者ともにPermissionの内容が同じであるため、この時点でPermissionが問題ではなさそうということがわかった(それならなぜPermissionがない旨のエラーがレスポンスされるのかは解せないが…)「タイプ」の値は、以前から使っていたほうは「Page」で、今回新たに発行したほうは「User」になっている。この部分はリンクになっていて、解説のドキュメントに飛んでいく。ただ、ここを読んでも、なぜPageだとダメでUserだとOkなのかの直接的な解につながる解説はない(と思う)。ドキュメントからするとPageのトークンはUserトークン発行後にしか作れないようなので、そういう意味ではPageのほうがなんとなく「強そう」ではあるが、単純に取得順序の違いがあるだけで、そもそも両者は性質が違うもののようではある。とにかく事実として、Pageトークンではメディアデータの取得はできず、Userトークンだとそれができるという結論に至った。

対処

グラフAPIエクスプローラーで発行したものは有効期限が超短命なので、少し期間を伸ばさないといけない。/oauth/access_tokenにリクエストを投げて、いわゆる昔「第2アクセストークン」と呼んでいたトークンを取得。アクセストークンデバッガーで調べて有効期限が「受け取らない」(これもよくわかってないが…楽観的に「無期限」を意味していると捉えることにしている)になっていることを確認のうえ、このトークンでAWS Lambda(Instagramの投稿をTwitterに連携するための自作ツールを動かしてるところ)の環境変数を更新。その日の夜のランニングの投稿が無事Twitterにまわったことを確認し、一旦動作確認完了とした。
しかし謎は多く残っている…

  1. 上の「調査1」のところで書いた、アプリケーションのPermissionの管理状況と方法が正直よくわかっていない。今どのPermissionを持っていて今後追加or削除する場合どうやってそれを作業するのか、がよくわかっていない。もっというと、Permissionの変更に伴うアクセストークンの再発行までの流れがわかっていない。今回、恐らくPermissionは問題になっていなかったので回避できているが、今後Instagram Graph APIが仕様変更で必要となるPermissionを変更した場合、即座に死亡する可能性がある。
  2. Permissionの変更作業そのものに関しては、上に書いた通りで、Standard Accessであれば申請に関しては面倒なことは必要なく、恐らくその場ですんなりPermissionが付与されるはずで、俺の使い方(使う範疇)であれば、恐らくそれで十分なので、こと「申請」に関してはあまり気にしていない。「恐らく」っていうのが多いのが若干気になってはいるが、恐らくそれで大丈夫なはずだ。というかもしクソ面倒なアプリ申請をしてまで手に入れなきゃならないAdvanced AccessのPermissionが必要になるようなら、俺は最早Instagram Graph APIを捨てる所存だ。そんな糞面倒なことやるくらいならスクレイピングするほうが多分マシだとすら感じている。。。

  3. 実はこの流れで、もう一つ別のアプリを作ってそっちで新たにPermission設定して…というのを考えて、実際アプリを作るところまでは行ったのだ。ただ、そもそも作るアプリの「種類」の部分からして分かれていて、これが正直わかりづらくて、ここで既に萎えかける。俺みたいなライトユーザー(ちょっとAPIでデータ抽出してきたいだけ、ってレベルの人)だと何選べばいいかわからんかつ、ここで選んだ種類に応じて初期設定されるPermissionも異なるように設定されているらしい。この「アプリの種類」を選択する部分は、記憶にある限り俺がInstagram Graph APIを使い始めた当時はなかったはずなので、上述したような「アプリ申請」云々を抜きにしても、Instagram Graph APIを使うまでの最初のステップがそもそもからして段々面倒くさくなっているのを感じた。こういう感じになってくると、新規のInstagram Graph APIユーザーが増えづらい気がして(そんな面倒なことやらなきゃならんならもうええわ的な)Developer Friendlyではないなあ~と感じてしまった。まあInstagram(Meta)側の事情も色々あるんだろうけどね。。

  4. いわゆる「第3アクセストークン」と呼ばれていた(はずの)、長期のトークンを発行するためのリクエストパス [user-id]/accounts が存在しなくなっている。検索しても見つからず、公式に提供されていない節を感じる。もしくは、アカウントの設定やアプリの状況によって、アクセスできないよう仕様が変えられたのかもしれない。ただ、その辺含めて特に更新履歴に記述は見当たらず、どういう経緯でこのリクエストパスが「見えなく」なったのか、理由が不明。

  5. というかトークンの期限についてはこれも含めて謎が多く、何をどう扱えばいいのか整理できていない。上記で書いた「第3アクセストークン」を取得するためにツールを自作したのだが、これを作った2021年2月時点においては、少なくともこの「第3アクセストークン」を発行しておけば、有効期限について気にする必要はないという話だった記憶があるのだが、そういう言説は今ドキュメントを見る限りでは見当たらなく、上記1.に書いたパスがなくなっている件を含め、トークン期限の仕様がわからない。

  6. むしろこの辺見る限りでは、長期のトークンでも最大60日程度の期限しか持てないような記述に見受けられる。「無期限」なんてものはなくなった?(もしくは幻想だった??)

  7. 一方で、アクセストークンデバッガーで調べると、「有効期限」欄に「受け取らない」という無期限を意味してそうな表記(楽観的解釈)があり、少なくとも60日とは明記されていないことから、今使ってるトークンの有効期限が実際いつなのか把握できない。「データの有効期限」欄の「3か月以内」という記述も気になる。そして今回新たに発行したはずのトークンの発行日が「約3年前」になっているのも何故だか不明。というかここの数値「1582645124 」をUNIX Timeだとして計算すると発行日が「2020/2/26」になり、「約3年前」ってほどでもない気がする。この辺が謎過ぎる。

  8. トークンのタイプが「Page」だとNGで、「User」だとOKな理由が不明。このドキュメント見る限りでは、アクセスするデータスコープの範囲が異なるためのように思えるが、だとしたら今までなんでPageのトークンで問題なく動作していたのかが不明。日本時間で9/21の夜(12:40UTC頃)にInstagramがこの辺の仕様を突如変えたのか、それとも昔からそうでなんらかの理由でたまたま生きていただけなのか、背景がわからない。

…とまあそんな感じで色々謎が残るが、とりあえず今は動くように復旧したので、一旦それでよいことにする。また死んだらそんときもう一度色々調べようと思う。Instagram Graph APIは(特にPlatform側の仕様は)わかりづらくて、というか読んでてあんまり面白みを感じなくて、ドキュメント読む気が失せるのが、「謎」感を強くしていると思う。どこかでちゃんと真面目に追跡しないといけないんだろうなあ…