読者です 読者をやめる 読者になる 読者になる

Smart Lock for Passwordsを利用したAndroidアプリログインフロー改善への取り組み

技術部モバイル基盤グループの児山です。

モバイル基盤グループでは、クックパッドのiOS/Androidアプリの開発だけでなく、アプリのユーザー体験を向上させるために新しい仕組みの調査や実装も行っています。 本稿ではAndroidアプリにおけるログインフロー改善の取り組みについてご紹介したいと思います。

モバイルアプリでIDとパスワードを入力してログインするのは大変です。 端末サイズが大型化してきているとはいえ、キーボードで1文字ずつポチポチメールアドレスを打つのはストレスが溜まりますし、安全な長いパスワードは入力する気が起きません。 特にWebサービスも提供しているモバイルアプリであれば、ChromeやSafariなどに保存しているWebサービスの認証情報をアプリでも使えたら…と思うことがよくあります。

実はSafariに保存した認証情報でのログインはiOSアプリで利用可能になっているのですが、AndroidではiCloud Keychainに相当する機能がなかったため実装できていない状態でした。 そんな中、今年のGoogle I/OにおいてAndroidでもSmart Lock for Passwordsが発表され、AndroidでもChromeに保存した認証情報を利用できるようになりました。 12月1日に公開したクックパッドアプリ v15.11.2.2 ではこのSmart Lock for Passwordsを利用してログイン補助機能を実装しています。

Smart Lock for Passwordsの動作例: Googleアカウントに認証情報が保存されている場合、以下のように自動的に補完入力を行います。

f:id:nein37:20151204142407g:plain

Smart Lock for Passwordsについて

Smart Lock for Passwordsという名前は長いのでついSmart Lockと略したくなりますが、実はSmart Lockというのは複数の機能の集合名です。 Smart LockにはSmart Lock for Androidという機能も含まれていますが、こちらは端末のロック解除を簡単にする機能で本稿の内容には直接関係ありません。 今回利用するChromeやAndroid端末からGoogleアカウントに認証情報を保存する機能はSmart Lock for Passwords、Androidでの実装はSmart Lock for Passwords on Androidという名前になっていますが、さすがに長過ぎるので以下ではSmart Lock for Passwordsとだけ書きます。

Smart Lock for Passwordsの動作はかなりシンプルで、認証情報の読み書き以外の機能はあまり持っていません。 主な機能は以下のとおりです。

  1. Googleアカウントに認証情報を保存する
  2. Googleアカウントに保存された認証情報を取得する
  3. Googleアカウントに保存された認証情報を削除する
  4. 他のアプリやサイトで使っているユーザー名やメールアドレスを認証のためのヒントとして取得する

Googleアカウントに、という表現の通り、Android端末にGoogleアカウントでログインしていない場合はSmart Lock for Passwordsは利用できません。 また、Google Play Servicesの機能なのでGoogle Play開発者サービスが入っていない端末でも利用できません。 Android 6.0 Marshmallowと同じくGoogle I/Oで発表されたため稀に勘違いされていますが、Android 2.3 (API level 9)から利用できます

ここまでは非常に簡単なのですが、実はAndroidではユーザーとGoogleアカウントが完全に1:1ではなく1人のユーザーが複数のGoogleアカウントでログインできるため、これを考慮すると挙動が一気に複雑になります。 しかもSmart Lock for Passwordsは複数の認証情報を保存することができるため、一人のユーザーが複数のGoogleアカウントでログインし、さらにGoogleアカウントごとに複数の認証情報を保存しているという状態もあり得ます。 発表当初はこの挙動についてドキュメントにあまり細かい説明がなくスクリーンショットもなかったため、実装前にSmart Lock for Passwordsが取り得る挙動についてひとつひとつ動作確認をするしかありませんでした。

以下はその調査内容の一例です。

認証情報保存時、ユーザー確認などがあるか

新しいIDを保存する場合は保存確認ダイアログを表示し、同一のIDの場合はユーザーに確認せず上書きを行う。

保存確認ダイアログ

f:id:nein37:20151204142430p:plain

複数のGoogleアカウントでログインしている状態で認証情報を保存しようとした場合どうなるのか

保存先のアカウントを選択するダイアログを表示する。

f:id:nein37:20151204142427p:plain

認証情報取得時、ユーザー確認などがあるか

認証情報が1件しかない場合はユーザーの同意なしにその認証情報を取得できる。 取得時には画面下部に青色の帯が表示される。

f:id:nein37:20151204142423p:plain

認証情報が複数ある場合はどれかひとつを選択するダイアログが表示される。 ユーザーがどれか1つを選ぶとその認証情報を取得できる。 この時は青色の帯は表示されない。 「上記以外」はダイアログのキャンセル動作(最近の更新で追加されたもの)。

f:id:nein37:20151204142419p:plain

アプリ側でUIの変更は可能か

ダイアログ表示のタイミングは制御できるがダイアログの文言やデザインの変更は基本的にアプリ側ではできない。 また、UIはGoogle Play Serviceのアップデートにより変更される可能性がある。

画像はSmart Lock for Passwords公開直後の認証情報取得成功時に出ていた帯。 右側にgマークが入っていた。

f:id:nein37:20151204142416p:plain

Webサイトとアプリでそれぞれ別の認証情報を保存するとどうなるか

Webサイト、アプリのすべての認証情報の中からひとつを選ぶダイアログが表示される。 ダイアログの見た目は通常の複数の認証情報から選ぶものと同じ。

複数のGoogleアカウントがそれぞれ認証情報を保存している場合に認証情報を取得しようとした場合どうなるのか

すべてのGoogleアカウントで保存されている認証情報の中から取得対象を選択するダイアログを表示する。 ダイアログの見た目は通常の複数の認証情報から選ぶものと同じ。

クックパッドアプリと同一のパッケージIDを持つアプリが認証情報を不正に取得することはできるのか

パッケージIDと証明書の組み合わせでアプリを特定しているため、証明書が異なるアプリでは認証情報を取得できない。 管理ページを見るとアプリから保存した認証情報は以下のURLの認証情報として管理されているように見える。

android://証明書か何かのハッシュ?@パッケージ名/

なお、Chromeの設定画面からパスワード管理を見た時はパッケージ名が先に来ている。

android://パッケージ名(途中で省略されて見えず)

本番環境と検証環境で認証情報を別々に保存することはできるのか

パッケージIDを変更すれば可能。 ただし証明書を変更するとChromeの設定ページで区別しづらくなるため、あまりお勧めできない。

上記のような調査はもちろん実装のためでもありますが、ユーザーが実際に機能を利用する時に直面する問題を知るためでもあります。 ユーザーの利便性向上のために入れた機能でユーザーが困ることがないよう仕様を完全に把握した上で導入し、開発者自身によるドッグフーディングによって問題の洗い出しを行っています。

導入への取り組み

Smart Lock for Passwordsを導入するにあたり、挙動を見ながら色々な実装を試した結果、既存のログインフローを大きく変更しないような形で実装することになりました。 当初は「インストール直後に起動すると自動的にログイン済み」というフローも検討していましたが、ログイン失敗時の処理やダイアログ表示などで逆にログインフローが複雑化してしまう懸念があったために現在はログイン画面内でのみ動作するようにしています。

実は7月ごろにはSmart Lock for Passwordsの実装はある程度形になっていたのですが、上記の懸念がリリース前になって持ち上がりました。開発者間で話し合った結果、一旦リリースは見送り、ドッグフーディングで検証・改善を行いつつGoogle社とも協議を行いました。 そのドッグフーディングの結果やGoogle Play ServicesのアップデートによるUIの改善を反映して、今月やっとSmart Lock for Passwordsを実装したアプリをリリースすることができました。

現在のクックパッドアプリが行っていることは以下の2つだけです。

  1. ログイン画面を表示した時にGoogleアカウントに認証情報が保存されていれば入力欄に補完する
  2. ログイン成功時に認証情報の保存を行う

結果的にSmart Lock for Passwordsのほぼ最小限の実装となっていますが、この実装により普段Chromeでクックパッドを利用していた新規アプリユーザーや機種変更をするユーザーの一部はキーボードに触れることなくログインすることができるようになっています。 今後もSmart Lock for Passwordsの利用状況やUIのアップデートにあわせて継続的にログインフローの改善に取り組んでいく予定です。 端末を買い替えたりタブレットを買い足したりしたとき、使っていてよかったと思ってもらえるようなクックパッドアプリを目指して行きたいと思います。

おわりに

本稿ではAndroidアプリのログインフロー改善に関する最近の取り組みについてご紹介しました。

クックパッドではモバイルアプリのより良いユーザー体験のために新しい技術を追い続けるエンジニアを募集しています。

興味がある方はぜひご応募ください。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/