開発中のiOSアプリのログイン画面に Password AutoFill 機能を組み込んで実機でのテストしているとき、ログイン情報の候補がキーボードの QuickType バーに表示されないという現象で苦労しました。
結論としては Firebase App Distribution でアプリをインストールした時のみ、アプリとドメインとの関連づけがうまくいかないことが原因だったのですが、その調査に苦労したため過程をメモとして残します。
はじめに
Password AutoFill とはiOS11から提供された、ログイン情報(ユーザーやパスワード)を自動入力する機能です。これをログイン画面に仕込んでおけば、Keychainなどのパスワードマネージャーに保存されているログイン情報を自動入力することができます。
以下は Twitter のログイン画面ですが、キーボード上部の QuickType バーに自動的に twitter.com 用のログイン情報候補が表示されているのがわかります。それをタップして生体認証 or パスコード入力を経ると、ログイン情報のテキストフィールドに自動的に入力されるという動作です。
これを実現するためには、大きく分類すると下記の2つについて対応する必要があります。
- ログイン情報を入力する UITextField の Content Type に
.username
,.password
を指定する - Associated Domains という仕組みで、ドメインとアプリの関連付けを行う
Associated Domains の確認
今回起きていた ログイン情報の入力時に QuickType バーに候補が表示されない という現象は、ドメインとアプリの関連付けがうまくいっていない可能性が高いです。
この Associated Domains の設定は、アプリとそのドメインのサーバーの両方で設定が必要です。
- アプリの Identifier に対して Associated Domains を有効にする
- アプリの Capabilities 設定で Associated Domains に関連づけるドメインを指定する
- 関連づけるドメインのサーバーに関連づけるアプリの Identifier を指定した apple-app-site-association というファイルを配置する
これらの設定方法についての詳細は割愛しますが、これらのどこを確認しても誤りは見つかりませんでした。
うまくいくケースといかないケースがある
確認中に、うまくいくケースといかないケースがあることに気づきました。それは、アプリのインストール方法によるものでした。
- Firebase App Distribution から AdHoc アプリをインストール
- TestFlight でアプリをインストール
- Xcode から実機に転送してデバッグ実行
- Apple Configurator で AdHoc アプリをインストール
つまり、Firebase App Distribution からのインストール時のみ上手くいかないのです。
Shared Web Credentials Daemon の動作を追う
調べていくと、どうやらドメインとアプリの関連付けはアプリのインストール/アップデート時に行われるようです。これは iOS の中での Shared Web Credentials Daemon というプロセスが行うため、デバイスを Mac に接続した状態でアプリのインストールを行い、Mac のコンソールアプリケーションによりログを追っかけてみます。
Apple Configurator で AdHoc アプリをインストールした場合
抜粋ですが以下のようなログが見つかりました。つまり、該当ドメインのサーバーに設置した apple-app-site-association ファイルを参照し、それを元にドメインとアプリIDを関連づけているのがわかります。先に .well-known
(RFC-5785) 配下を探しに行くようです。
swcd Started request for domain 'example.com', URL 'https://example.com/.well-known/apple-app-site-association'
swcd Added service 'webcredentials', appID 'TEAMID1234.com.example.someapp', domain 'example.com'
swcd Skipping request for domain 'example.com' when already outstanding
swcd Started request for domain 'example.com', URL 'https://example.com/apple-app-site-association'
swcd Completing request for 'https://example.com/apple-app-site-association', status 0/0x0 noErr
swcd Updated app ID 'TEAMID1234.com.example.someapp', domain 'example.com', flags 0x0 < > -> 0x2 < SiteApproved > on check
ちなみに、アプリを削除した時には次のようなログが出ており、関連づけも削除されているようで。
swcd Removed service 'webcredentials', app ID 'TEAMID1234.com.example.someapp', domain 'example.com' by bundle ID 'com.example.someapp'
Firebase App Distribution から AdHoc アプリをインストールした場合
抜粋ですが以下のようなログが出力されています。前のものと比べると2点違いがありました。
-
Added service 'webcredentials' ...
の直後にRemoved service 'webcredentials'
されてしまっている - これが原因なのか
Updated app ID ...
のログがない
原因はわかりませんが、Firebase App Distribution からインストールした場合は、アプリとドメインの関連づけがうまくいかないようです。
swcd Started request for domain 'example.com', URL 'https://example.com/.well-known/apple-app-site-association'
swcd Added service 'webcredentials', appID 'TEAMID1234.com.example.someapp', domain 'example.com'
swcd Skipping request for domain 'example.com' when already outstanding
swcd Removed service 'webcredentials', app ID 'TEAMID1234.com.example.someapp', domain 'example.com' by bundle ID 'com.example.someapp'
swcd Started request for domain 'example.com', URL 'https://example.com/apple-app-site-association'
swcd Completing request for 'https://example.com/apple-app-site-association', status 0/0x0 noErr