Carpe Diem

備忘録

OAuth 2.0 for Native Apps

背景

以前紹介したように、モバイルアプリにログインする際にOAuth 2.0の認可フレームワークを使ったものがあります。

christina04.hatenablog.com

これはRFC 6749のOAuth 2.0 Authorization Framework を使ったものですが、この中で曖昧だった(それによってセキュリティ上よろしくなかった)部分を「ネイティブアプリのベストプラクティス」として具体的にしたものとして、RFC 8252のOAuth 2.0 for Native Appsが作られました。

OAuth 2.0 for Native Apps

特徴

特徴としては以下です。

  • Implicit Flowはセキュリティ課題があるため、Authorization Code Flowを使う
    • ただしPKCEが必須
  • 組み込みWebViewではなく、外部ブラウザを使って認証を行う
    • WebView「ホストアプリが資格情報を盗み得る」「共有 Cookie が使えず SSO 性能が落ちる」といった課題があるため

PKCEとは

RFC7636 PKCE(ピクシー)とはProof Key for Code Exchangeの略で、認可コードフローにおいて認可コードの横取り攻撃を防ぐためのRFCです。

モバイルアプリやWebクライアントはパブリッククライアントであり、クライアントシークレットを持つとセキュリティ上課題があります。
なのでクライアントシークレットを使わずとも認可コード生成を依頼したクライアントであることを証明するための仕組みです。

以下のパラメータを使って実現します。

  • code_verifier
    • 文字数:43~128文字
    • 使用可能な文字:半角英数字(azAZ09)と記号(-. 、_~)からなるランダムな文字列
  • code_challenge
    • code_verifierをSHA256でハッシュ化してBase64URL形式にエンコードしたもの

シーケンス図で使うタイミングを後述します。

シーケンス図

シーケンスを説明すると以下です。

# フェーズ 主なやり取り 目的
1 認可リクエスト ネイティブアプリが外部ブラウザを開き
/authorize? response_type=code & code_challenge=… を送信
「このユーザーが どの権限 を外部アプリに委譲するか」認可画面を表示するため
2 ユーザー認証 & 同意 ブラウザで IdP ログイン → 同意ボタン → 302 で redirect_uricode を付与 認可サーバーが 一時的な認可コード を発行し、アプリへ戻す
3 トークンリクエスト アプリがバックチャネルで /token
codecode_verifier を POST
認可コードを アクセストークン/リフレッシュトークン に交換(PKCE により横取りを防止)
4 (オプション)リソースアクセス Authorization: Bearer <access_token> で API を呼ぶ 取得したトークンで保護リソースにアクセス

ユースケース

U-NEXTのようにモバイルアプリのログイン画面に「Webでログイン」といった導線を用意する

(実際は不明ですが)このUI・UXはOAuth 2.0 for Native Appsのユースケースと合致しており、外部ブラウザでログインして認可コードを発行してもらい、モバイルアプリをログインさせることができます。

Web上で決済を促した後、すぐにアプリにログインできるように

広告やメール内リンクからWeb で決済し、そのままアプリで続行するパターンです。

  1. Web でアカウント作成+決済完了
  2. 完了画面に Universal Link / App Link(例: https://example.com/continue)を配置
  3. リンクタップでアプリが起動(iOS: Universal Link, Android: App Link)
  4. OAuth 2.0 for Native Apps の開始
    • モバイルアプリ上でcode_verifier, code_challengeを生成
    • 外部ブラウザ起動
    • すでにWebでアカウント作成済み(=認証済み)なので認可のみ行う
  5. モバイルアプリで code(認可コード)受け取り
  6. モバイルアプリからcodecode_verifierを渡してアクセストークンをリクエスト
  7. アクセストークンを取得してログイン完了

このような手順で可能です。

まとめ

過去にimplicit grant flowを使うと車が通れるほどのどでかいセキュリティー・ホールができるといった話があったように、認証・認可周りはセキュリティリスクに気をつける必要がありますが、今回のRFCであるOAuth 2.0 for Native Appsはそういった気をつける点を明記されたことでセキュアな方法でログインできるようになりました。