Edited at

iOS 11 / Android O 時代のアプリ認証

More than 1 year has passed since last update.

⚠ ものすごく雑に調べた内容をまとめているだけなので、間違ってるかも。


TL;DR


  • Web サイトのパスワード管理と同じように、アプリにおいてもパスワードマネージャから自動的にテキストフィールドに入力する仕組みができた。

  • Android O はマネージャアプリを選択して、参照および保存することができる。

  • iOS 11 は Safari や iCloud キーチェーンに保存されている情報を参照のみすることができる。


Autofill の登場

従来、アプリケーションがログイン機能を持つ場合には、よくあるログインフォームへ ID と Password を打ち込みますが、それらの情報はアプリ内部で閉じているのが当たり前でした。

サービスやアプリごとに異なる高い強度のパスワードを使い分けたい場合、パスワード管理アプリを使うのが一般的でした。

iOS 11 / Android O では共に Password Autofill の仕組みが搭載され、Web ブラウザのパスワードマネージャのように、記憶したパスワードの外部での管理、および Web ブラウザの認証情報と連動した ID / Password の自動入力が行われるようになります。


OS ごとの仕様の違い

iOS 11
Android

パスワードマネージャの選択
Safari / iCloud キーチェーンのみ
設定の「自動入力サービス」から任意選択可能

パスワードマネージャの実装
不可能
可能

アプリからのパスワードの保存
不可能
可能

アプリと Web サイトの紐付け
あり
なし

Autofill 可能な入力欄

UITextView / UITextField(※1)

EditText / Spinner 等(※2)

Autofill となる情報の対象
ログイン ID とパスワード
アカウント情報以外にも電話番号、クレジットカード情報など

※1 UITextInputUITextInputTraits プロトコルに準拠した任意のビューでも可能っぽい説明がセッション内にあった。

※2 Autofill Framework 関連のメソッドは View クラスに追加されているので、すべての

View およびカスタムビューにて Autofill が可能。


iOS

TextContentType プロパティに .username または .password を設定する。

QuickType Bar が表示されるので、そこから認証情報を選択し、自動入力することができる。


Web サイトとの紐付けについて

もしプロジェクト設定で、Associated Domains でアプリと Web サイトを紐付けている場合、


  • Web サーバーを https 対応する


  • apple-app-site-association ファイルを配備する

  • 該当ドメインのサイトに事前に Safari にてログインしている

ことで、QuickType Bar にアプリに関連付けられた Web サイトの認証情報が第一選択として表示されます。


Shared Web Credentials と違うの?

iOS8 以降では、SecRequestSharedWebCredential() 関数を呼び出すことで、アプリと Web サイトを紐付けている場合に限り、認証情報を取得することができました。

Autofill はこの制約がないので、Safari パスワードマネージャ / iCloud キーチェーンの認証情報をもっと気軽に使えるようになったもの、というような認識でいいのではないかと。たぶん。


パスワードの保存はできないの?

Autofill については、読み込み限定じゃないかなぁ…。

Shared Web Credentials の SecAddSharedWebCredential() 関数を使えば、書き込みや上書きを行うこと自体はできるので、apple-app-site-association をサーバーに配備しておけば、Web サイトを持たないサーバー認証でも Autofill が有効にできるのかも?


SSO の類はどうすればいいの?

アプリのログインのユーザー体験はちょっとだけマシになるのですが、逆に悪くなったのが OAuth などの SSO です。

iOS 10 までは Safari と SFSafariViewController の認証情報が共有されていたので、一度だけ Safari でログインしていれば、アプリでは OAuth リクエストの画面をすぐに出すことができたのですが、トラッキング cookie を埋め込む目的で使われるのを防ぐためか、アプリは Safari と独立した cookie ストレージを持つように変更されました。

iOS11 beta3 で SFAuthenticationSession というクラスが追加されたので、これで頑張ってねという感じだと思います。


どういう人向けか

iCloud キーチェーンを有効にして、macOS でも Safari を使っている Apple ユーザーにとっては最高の仕組みだと思います。

そこから一歩でも外れると(普段使いのブラウザが Chrome だとか、Windows + iPhone のユーザーとか、1Password などのサードパーティアプリに認証情報を集約とか)、そこまで恩恵に預かれない感じですね。


Android

設定より、「言語と入力」>「詳細設定」>「自動入力サービス」を設定する。

自動入力が必要な View かどうかは、android:importantForAutofill 属性にて指定する。

デフォルトでは auto となっており、これはシステムがヒューリスティクスに判定する。もし該当の View、またはその子階層の View 群が Autofill を必要としない場合、この設定で余計な走査を行わないようにできる。

基本的にそのままでも動作しますが、Layout XML の android:autofillHints 属性、もしくはコード上で setAutofillHints() を設定することで種別のヒントを提供することができる。


自動入力サービスの作り方

android.service.autofill.AutofillService を継承し、適切にマニフェストに登録することで作成できる。

onFillRequest()onSaveRequest() をオーバーライドして実装する。それぞれ Autofill の要求・入力した内容の保存の要求があった場合に呼び出される。Android の Autofill では、アプリ側からデータの保存要求が送られることがある。

このとき、現在の入力内容を保存するかどうかの判断をどのように行っているのか、については未調査です。


セキュリティ的に問題ないのか?

これは AutofillService の実装に依存します。

例えばパスワードを暗号化せずに SharedPreference に保存するだけのような、とても脆弱な AutofillService も実装することもできてしまいます。Android Keystore システム などのような、適切な暗号化の措置が取られていることを祈るしかありません。

今年の3月にも LastPass に深刻な脆弱性があることが発覚したように、攻撃者にとってパスワードマネージャというのは恰好の的でもあり、Android フレームワークが Autofill Framework をサポートすると共に、普及も進むことで、同時に攻撃手段の巧妙化が進むという可能性が否定できないところではあります。


どういう人向けか

Google Passwords と連動する自動入力サービスは確実に登場するでしょうし(既にある?)、これまで使ってきたパスワードマネージャが Autofill Framework に対応すればそのまま移行することができるので、比較的誰でも使いやすいと思います。

また、Web サイトを持たないアプリでもパスワードを外部で管理できる、というところが iOS と比較して大きなメリットだと考えます。

他方、自動入力の対象は ID / Password に留まらず、クレジットカード番号やその他個人情報などの機微情報を含むことができるため、セキュリティ事故に繋がるのでは?という懸念もあります。


資料


一次資料


その他参考にしたもの