Automatic Strong Passwords and Security Code AutoFillのざっくりとした内容メモです。内容、画像は全てセッション動画から持ってきています。
パスワードの自動入力
今までのパスワード管理と入力
今までパスワード管理はユーザにとって悩みのタネだった。セキュリティ強度が高いパスワードを各サービスごとに用意する必要があるが、それはパスワードマネージャーを使ったとしても面倒なことだった。そこで今回、パスワードで憂慮することなく、簡単に、安全に管理できるようにした。
現在、多くのユーザはiCloud Keychainを使っている。Apple自身もKeychainにはアクセスできないため、Keychainでの管理は生体認証の次に安全で簡単な方法である。これがiOS 12でもっと簡単になる。
iOS 12からのパスワード管理と入力
新規アカウント作成画面でメール欄にフォーカスするとユーザ名がサジェストされる。サジェストは今までKeychainに保存されていた情報を元にされる。
次にパスワード欄にフォーカスするとセキュリティ強度の高いパスワード候補が提示される。もちろん今までのKeychain同様、他のデバイスでもパスワードを引き継いで使うことができる。たった数回のタップでサインアップすることができる。
再度このアプリにログインする場合はこのようにサービスごとにIDとパスワードのセット候補が表示されます。これをタップすると生体認証が起動し、生体認証に成功すると自動でID、パスワード欄が入力されます。
2ファクター認証がかかっている場合は、テキストメッセージを受信した時に認証コードがキーボード上部に表示され、これをタップするだけで認証コードの入力ができる。
実現方法
このパスワードの自動入力技術はwebベースで作られている。QuickType bar(キーボードの上の、候補が表示される欄)に認証情報を表示するには、この入力欄が何のサービスのものなのかを判断できるよう、アプリとドメインを対応させる必要がある。関連付けはいたって簡単で、アプリのentitlementsファイルとサーバ側の認証情報ファイルを少し変えるだけでよい。これについてはWWDC 2017のIntroducing Password AutoFill for Appsで紹介しているのでこれも見ると良い。
ネイティブ側でやることとしてはContent typesの設定がある。適切なFieldに適切なtypeを指定する。
let userTextField = UITextField()
userTextField.textContentType = .username
let passwordTextField = UITextField()
passwordTextField.textContentType = .password
WKWebviewもAutoFillをサポートしている。パスワードマネージャーに関する具体的な実装方法はImplementing AutoFill Credential Provider Extensionsを参照すると良い。
新しいアカウントでログインするとその認証情報を保存するかどうか聞かれる。ここで保存すると他のデバイス、SafariでもAutoFillの恩恵を受けることができる。
パスワード保存のフロー
- ログインシナリオを推測
- 関連するドメインを元に適格性をチェック
- ユーザ名とパスワードを見つけ出す
- サインインアクションを検知
- パスワードを保存or更新するかどうかを聞く
適合性チェック
パスワード保存周りに関してはiOS 12で目新しいものはないが、適合性を確かめたいなら以下のことを確認する。
- Fieldに適切なcontent typeを付与していること
- ログインフォームをview階層から除外していること
- view階層から除外した後にログインフォームをクリアすること
- 正しいドメインに保存していること
- SecAddSharedWebCredential()はもういらなくなった
重要ポイント
- アプリとドメインを関連付ける
- Fieldに適切なタグを付ける
- ログインしたということを検知する
セキュリティ強度の高いパスワードの自動生成
サインアッププロセスを簡単に、安全に、便利にした。ユーザはもう面倒なことは考えず、数回タップすればよい状態になる。
セキュリティ強度の高いパスワードの自動生成フロー
- ViewControllerのタイプを推測
- 関連するドメインを元に適格性をチェック
- 対応するログインフォーム要素を検知
- ユーザ名フィールドにフォーカスしたらユーザ名をサジェスト
- パスワードフィールドにフォーカスしたらセキュリティ強度の高いパスワードが自動入力される
適合性チェック
※AutoFillと項目は同じ
コードに関しては、ユーザ名のFieldはAutoFillの時と同じだが、パスワードの方はiOS 12で新しく登場したnewPassword
を指定する必要がある。
let newPasswordTextField = UITextField()
newPasswordTextField.textContentType = .newPassword
let confirmPasswordTextField = UITextField()
confirmPasswordTextField.textContentType = .newPassword
ちゃんと適切なFieldを検知するために、UITableViewで認証画面を作る場合は1つのセルに置くUITextFieldは1つにする必要がある。
心に留めておくこと
-
.username
と.newPassword
のフォームは同じ画面に配置する - ユーザ名フォームはread-onlyにできる
- パスワード変更フォームにも同じように適用する
パスワードフォーマット
- 20文字
- 大文字、数字、ハイフン、小文字を含む
- エントロピーが71ビット以上
- ほとんどのサービスと互換性がある
セキュリティ強度の高いパスワードの自動生成は、カスタムルールを作って自分で定義することもできる。
let newPasswordTextField = UITextField()
…
let rulesDescriptor = "allowed: upper, lower, digit; required: [$];"
newPasswordTextField.passwordRules = UITextInputPasswordRules(descriptor: rulesDescriptor)
Password Rules Validation Toolというのがあるので使ってみると良い。
デモ
EmailのTextFieldはContent Type = Username
、Keyboard Type = E-mail Address
を、PasswordのTextFieldはContent Type = New Password
、Secure Text Entry = true
を指定してデモを見せる。多くの場合はここまでの設定だけで良い。ただ今回のサービスではパスワードに$
を含めることを必須としており、バリデーションエラーになってしまった。この場合パスワード生成ルールに手を加える必要があるのでPassword Rules Validation Toolページに飛び、required
に'$'を指定する。成形されたものはUIKit用、HTML用が出力される。今回はUIKit用のテキストをコピーし、Storyboard - Password の TextField - Password Rulesの欄にペーストした。
重要ポイント
- アプリとドメインを関連付ける
- Fieldに適切なタグを付ける
- ログインしたということを検知する
- (必要があれば)独自のパスワードルールを作る
セキュリティコードの自動入力
2ファクタ認証などの、テキストベースのセキュリティコードの自動入力を可能にするためには以下のように.oneTimeCode
を使用することと、システムキーボードを使うことが求められる。
let securityCodeTextField = UITextField()
securityCodeTextField.textContentType = .oneTimeCode
セキュリティコードを含んだメッセージは、サポートされている全ての言語で利用することができる。
この機能はiOSだけでなくmacOSでも使うことができるし、ネイティブだけでなくSafariでも使うことができる。加えて、例えばMacのSafari上でセキュリティコードが必要になった時に、iPhoneで受け取ったセキュリティコードを自動入力することもできる。
AutoFillをSafariで使う場合は以下の表に従って設定をする。
Federated認証
今までFederated認証を使おうとした場合はこのような表示が出ていました。
それがボタンを1回タップするだけでスムーズにSafariとCookie共有ができるようになる。ASWebAuthenticationSessionを使うメリットとしては以下の通り。
- ログインフローが早くなる
- サードパーティだったとしても特に気にすることなく使うことができる
- パスワード自動入力、セキュリティコードの自動入力に対応している
- 簡単なブロックベースのAPIになっている
使い方
import AuthenticationServices
guard let oauthURL = URL(string: "https://www.example.com/oauth/...") else {
return
}
self.authenticationSession = ASWebAuthenticationSession(url: oauthURL, callbackURLScheme: nil) { (callbackURL, error) in
guard error == nil, let callbackURL = callbackURL else {
// Process error.
return
}
// Process token.
}
self.authenticationSession.start()
新しいパスワード管理機能
iCloud keychainで他のデバイスでも認証情報を共有することができる。Siriに「○○サイトのパスワードを教えて」と言うと入力してくれたりもする。
iOS 12では設定アプリのパスワードページのデザインが変わり、パスワードのコピーなどができるようになっており、パスワードをAirDropで送ることもできる。これはmacOSでも同様である。
もう一つ大きな変更がある。もし複数のwebサイトで同じパスワードを使っていた場合、同じパスワードを設定しているwebサイトを教えてくれ、さらにこの画面上でパスワードの変更ができる。
tvOSでもAutoFillの恩恵を受けることができる。詳しくはWhat's New in tvOS 12を参照すると良い。
まとめ
- AutoFillはパワフル
- この機能は自動で動く
- 使えるかどうか確認するためにテストをするように