GoogleのOAuth 2.0実装からみえたClientの扱い

こんばんは、ritouです。

idconの後、Public Clientに対してどのGrant-Typeを使わせたらいいのかを考えたりしましたが、まぁこれは見なくていいです。
Oauth 2.0 public client · ritou/r-weblife Wiki · GitHub

で、そのときに参考にしたGoogleのOAuth 2.0実装の自分なりの解釈を残しておきます。

Using OAuth 2.0 to Access Google APIs  |  Google Identity Platform  |  Google Developers

対象のClient

  • Web Server Applications : Webサービス
  • Client-side Applications : JSアプリとか
  • Installed Applications : モバイルアプリとか
  • Devices : ゲームとかデジカメとか
  • Service Accounts : ユーザーが介入しないリソースアクセス

んで、それぞれにどのGrant Type(Profile)を使わせるかと。

Clientの種類 Grant Type 補足
Web Server Applications Authorization Code Grant
Client-side Applications Implicit Grant フラグメント使うからServerに送られない。検証APIも提供
Installed Applications Authorization Code Grant iOS/AndroidはBundle IDやパッケージ署名などを利用、それ以外はsecret発行
Devices Authorization Code Grant Installed Appと同じ扱い
Service Accounts JWT Bearer Token Profile Client Credentialsは使わない

実は、別にこんな表いらなかった。
3行でまとめると

  • JSアプリのようにHTTPのバックエンドにアクセスされたくないケースはImplicit
  • それ以外のユーザーが絡むClientはAuthorization Code Grant
  • ユーザーが存在しない2leggedなClientにはClient Credentials Grantではなく”JWT Bearer Token Profile”という拡張仕様

となっています。

JSアプリにToken 検証APIは必要?

Client Applicationのフローでは、GoogleはJSアプリからAccess Tokenの検証した後にリソースアクセスしろといっています。
この、Implicitで受け取ったAccess TokenをClient側で検証することについては今までも今後も議論が尽きない部分だとは思いますが、OAuth 2.0の仕様の範囲内で”検証したいClientにはその手段を提供しておく”という意味合いなのかなと。

ちなみにOpenID Connect対応を正式に宣言していないのでそのあたりの動き次第で方針が変わるかもしれません。

Installed Appにsecret埋め込み

Public Clientにsecretを埋め込む一番の問題は、様々な方法で抜かれたsecretを使ってClient Credentials GrantのAccess Token取得ができてしまうことです。
しかし、Facebookを利用しているアプリのように啓蒙活動だけではこれを防ぐことは難しいでしょう。

GoogleはService Accounts Applicationとして、ユーザーを介さないフローにClient Credentialsを提供する”のではなく、JWT Bearer Token Profileを採用しています。
JWT Bearer Token ProfileとはJWT形式のAssertionを用いてAccess Tokenを取得、Client Authenticationができるような拡張仕様であり、GoogleAccess Token要求に用いています。
もともとはAssertion FlowとしてSAMLなど他のシステムとの連携に利用できるように議論されていたものだと認識しています(もしかしたら間違ってるかも)。

Service Accounts Applicationを利用しようとするとJWT署名作成/検証のためのRSA鍵ペアを生成し、秘密鍵のダウンロードを促されます。Access Token Requestにはclient_secretが含まれないため、secret漏洩時の一つのリスクをつぶせます。

あとはredirect_uriの重複やオープンリダイレクタを利用したなりすましのリスクも考えられるわけですが、まぁこれはredirect_uriの管理によって対応しようと考えているように見えます。

その他

他にもこのあたりは参考になるかなと思います。

  • iOS/Android Appに対してはアプリを特定できる識別子を用いている
  • Installed Appではurn:ietf:wg:oauth:2.0:oob をredirect_uriに指定するとブラウザにAuthorization Codeが表示されてユーザーが手動入力できる
  • Project単位で利用できるscopeを指定できるため、悪意のある第3者による意図しないscope指定を防げる

OAuth 2.0は仕様がRFC化されてあとはどれだけ解釈の中で脆弱性を生まない実装をしていけるかが重要ですね。

ちなみに、OAuth 2.0まわりだとGoogleについてよく書いてますがなんちゃらエキスパートでもなんとかフラグでもありません。
ではまた!