理系学生日記

おまえはいつまで学生気分なのか

OAuth2.0を利用するネイティブアプリの注意点

OAuth 2.0 をスマートフォンのネイティブアプリに提供することになりそうだったので、この一週間くらい RFC を読み続けていました。 しかしですね、Web アプリケーションが OAuth 2.0 のクライアントとなるケースは想像できるようになったんだけど、iPhone アプリに代表される Native App を OAuth 2.0 に対応させるケースがなかなか想像できない。 それでも色々調べて調べて、ようやくどういう形で実現されるのかが分かってきたので、ここでまとめてみます。

OAuth 2.0 の概要

いろいろ読んでみたけど、OAuth 2.0 の概要だったらこの 2 つの RFC を読めば良いと思います。

アクセス権限付与フローには Authorization code flow を使う

OAuth 2.0 にはいくつかフローがあって、いろんな観点からどのフローを使うかを選択することになります。当然その観点には様々なものがあるわけですが、世間一般のベストプラクティスとされているのは、Authorization Code Grant です。

他には Implicit Flow が候補に挙がるのですが、Implicit Flow は Custom URI Scheme 上書き攻撃に対して脆弱で、PKCE (Proof Key for Code Exchange by OAuth Public Clients) を挟み込む余地がありません。

実際、まだ draft ではありますが oauth working group が提出している OAuth 2.0 for Native App でも、Implicit Flow は非推奨とされています。

However, as the Implicit Flow cannot be protected by PKCE (which is a recommended in Section 7.1.1), the use of the Implicit Flow with native apps is NOT RECOMMENDED .

ブラウザは外部ブラウザを使う

Web-View ではなく、外部ブラウザを使う方がセキュリティが高くなります。 これは、Native App の中で Web-View を使うと 3rd Party が作る可能性のある Native App が直接ブラウザを制御でき、ブラウザの機能 (cookie やユーザ入力の監視) を利用して認可コードやアクセストークン以外の情報を入手できてしまうからです。 また、同じ認可サーバを使用する他のアプリケーションがあったとしても、Web-View だと認証状態が共有できないっていう欠点もあり、UX を損ねるという観点もあります。

ただ、最近のスマートフォン OS の進化からか、Web-View と同様に Native App の中でブラウザを起動でき、外部ブラウザと同じセキュリティ的なメリットを享受できる API を保持するようになっています。 iOS の場合は SFSafariViewController、Android の場合は Chrome Custom Tab ってヤツです。

PKCE をサポートする

この話は長くなるので、PKCE は別途エントリを書こうと思います。 一般的な Native App (ここでは、RFC 6749 の定義として "Public" なクライアントを"一般的"と形容しています) では、この PKCE のサポートは実施しておいたほうが良さそうです。

アプリ自体の認証は実施しない

Native App の中の秘匿情報なんてのは、どんなに頑張ったって容易に漏洩し得る (メモリの中は覗けますし、実行ファイルは逆コンパイル/逆アセンブルできますし) ので、そういう情報には信を置けません。 そういう情報をベースにしたアプリケーションの認証 (RFC ではクライアント認証: Client Authentication と呼んでいます) は非推奨になっています。