以前ネイティブアプリ用のRailsAPIを作成したときに感じた素朴な疑問があり、他社さんの事例から少し勉強させて頂きました。疑問というのはログイン不要で取得できるGETAPIについての下記のようなもの。
- 非公開APIをブラウザ直打ちでみれるのってどうなんだろう?
- アプリ以外からはAPIにアクセスさせないことってできるのだろうか?
- 認証が使えないけど、根本的な対策はあるのだろうか?
ちなみに僕が作っていたのがニュースアプリだったので今回はG社、U社、S社さんについて調べさせて頂きました。サービスの特定に繋がる部分は伏せ字にしてあるのでご了承下さい。
事前準備
mitmproxyという自分のPCとネイティブアプリを同ネットワーク上に置くことでproxyサーバーのように経由することができる便利なツールがあったのでそれを利用してます。
ネイティブアプリ→mitmproxy実行中PC→外部サーバーという具合に接続してHttpRequestの解析を行います。
詳細設定は上記リンクからよろしくお願いします。
事例
G社
テレビコマーシャルを頻繁に出していて有名なあのアプリです。
GETAPIは下記。
https://hoge/articles/2/18/article_22647051.json?updated_at=1487410380
ブラウザで叩くことができました。
誰でも見れるデータについては秘匿性は特に重要視しないということでしょうか。
U社
ビジネスマン向けのニュースアプリを出しているU社です、記事のクオリティが高くて好きです。
GETAPIは下記。
https://hoge/summaries/news?theme=technology
見れました。
S社
3社の中だと1番大衆向け?なアプリのS社です、僕のまわりにも使っている人が沢山います。
しばらくrequestのログを眺めていたんですが、それらしいGETRequestが見つからなかったです。
ですが、よくよく眺めてみたらありました。
POST https://hoge/api/v2/refresh
なるほどGETじゃなくてPOSTでデータを取得してるんですね、たしかにこれはブラウザではデータの取得が行えない、下記のようなPOSTRequestをCurlで叩くとデータの取得が行えました。
curl -X POST
-H "Accept: application/json"
-H "User-Agent: hoge"
-H "Content-Type: application/x-www-form-urlencoded"
-d "version: hoge"
-d "timestamp: 1487399400948"
-d "filters: twitter"
-d "deviceToken: hoge"
-d "countryCode=jp" -d "locale=ja_jp"
-d "edition: ja_JP"
-d "unselectedChannelIdentifiers: cr_ja_twitter,cr_ja_apps_ios_all"
-d "language: ja"
-d "since: 1487394760864"
-d "timezone: Asia/Tokyo"
-d "channelIdentifiers: cr_ja_entertainment,cr_ja_sports,cr_ja_column,cr_ja_humor,cr_ja_national,cr_ja_politics,cr_ja_economy,cr_ja_technology,cr_ja_international,cr_ja_vid
eo,cr_ja_food,cr_ja_extra_animal,cr_ja_column_family,cr_ja_extra_manga,cr_ja_column_career,cr_ja_column_living,cr_ja_entertainment_animation,cr_ja_column_love"
-d "until: 1487399400947"
https://hoge/api/v2/refresh
POSTRequestを送る以外にも送信データにUser-AgentやdeviceTokenなどをもたせ秘匿性をあげているようです。
まとめ
非公開GETAPIの是非を考えてみました、3社ではありますが他社事例を調べたことで以下のような感想を抱きました。
GETAPIのセキュリティ対策は難しい
queryでパラメータを持たせるくらいしか策がないなという印象です。それでも普通にブラウザから叩けちゃいますね。
必ずしもRESTである必要はない
RailsのようなRESTを強く意識したフレームワークを使っているとGETやPOSTの役割を過剰に意識しすぎます、凝り固まらずにその時々最適な方法を取りたいと思いました。
GETとPOSTの違いはデータ送信量とその秘匿性
上の話に近いですが本来はGETとPOSTはデータを送信するという意味では役割は同じです、そしてデータ送信量やその秘匿性の意味合いではPOSTのほうがメリットは大きいと思います。GETはブラウザを介さないアプリであれば使わなくてもいいかなと思いました。
親切なエラー文言は良いヒントになるから本当は気をつけたほうがいい
これは解析側に回って初めて感じたことなんですが、不正なRequestがAPI側に送られるとBadRequestのような例外文言が返ってくるのですが、この文言が丁寧すぎると解析側に良いヒントを与えることになるなと思いました。開発者側にとってはありがたいんですけど。POSTでデータ取得をしていたS社さんは基本的にエラー文言はERRORとしか返ってこなく、考えて実装しているんだろうなと感動を覚えました。
以上非公開GETAPIについて考察してみました、
しっかり調べたつもりですがもしも解析対象のAPIが非公開でなく公開だったらすみません。
それでは!