スタディサプリ Product Team Blog

株式会社リクルートが開発するスタディサプリのプロダクトチームのブログです

Credential Managerに移行するために調べたこと

こんにちは。スタディサプリ Androidエンジニアの@morayl@omtians9425 です。

スタディサプリのAndroidアプリでは、ID/パスワードの記憶に CredentialsApiを使っている箇所がありました。現在はCredential Managerが推奨となっており、そちらへ移行するために調べたことをまとめました。
「ID/パスワードの記録」の性質上、実装の確認や検証では「その記録をリセットする」ことが必要になるので、その方法についても解説します。

ライブラリandroidx.credentials:credentials1.3.0を利用しました。

移行の背景

Smart Lock for Password(CredentialsApi)は2022年にdeprecatedになり、com.google.android.gms:play-services-auth:21.0.0から削除されています。 これにより、21.0.0以降ではCredentialsApiを使うことは出来ません。
それに変わる新しいAPIとして、Credential Managerが登場しています。ライブラリが変更になっているため、推奨APIを使うためには、単純なバージョンアップだけでなく、コードの書き換えが必要です。

移行方法

公式のマイグレーションガイドが用意されています。 developer.android.com

準備

ガイドのSign in with passwords using Credential Managerに実際の移行手順が載っていて、dependenciesやproguardの記載、その他必要な手順が書かれています。
dependenciesは、Android13(API33)以前の端末をサポートする場合、androidx.credentials:credentials-play-services-authが必要になります。
minSdk>=33でなければ必要なので、現状ほぼ必要だと言えるでしょう。

パスワードを保存する

マイグレーションガイドをぱっと見るとコード例は読み取りしかないのですが、Sign in with passwords using Credential ManagerSave a user's passwordのリンクがあります。

簡単な流れとしては、CredentialManager#createCredentialに、IDとパスワードを入れたCreatePasswordRequestを渡すだけです。

呼び出すとこのようなボトムシートが表示されます。

パスワード保存ボトムシート

ただしこのメソッドにより表示されるパスワード保存ボトムシートに Activity Context が使われるため、呼び出しタイミングには注意が必要です。例えばログイン成功時に別の Activity に遷移するようなケースでログイン画面の Context が直ちに破棄される場合、クラッシュするリスクがあるため遷移先の Context を用いるとより安全かもしれません。

保存済みのパスワードを取得する

Sign in with saved passwordsで解説されていますが、suspendな関数CredentialManager#getCredentialを使うと、結果を取得でき、そこの結果からIDとパスワードが取得できます。
この方法で、マイグレーション前のアプリでCredentialsApiを使って保存したID/パスワードも取得することが出来ます。

保存済みのパスワードがあると、このようなボトムシートが表示されます。

パスワード読み出しボトムシート

保存されたパスワードを更新する

現状、CrendentialManager には明示的にパスワードを更新する API がなさそうでした。再度パスワード保存することで上書きできるため、ユーザーが手入力した場合は一律パスワードを保存することによって新規保存・更新の両方に対応しています。

保存されたパスワードを削除する

CredentialsApiでは、保存したIDとパスワードを削除することが出来ました。昔のドキュメントにも、下記のように削除について記載があります。

developers.google.com

Delete credentials from Smart Lock when either of the following circumstances occur:

  • Signing in with the credentials fails because the account no longer exists or the password is incorrect.
  • The user completes the app's account deletion flow.

To delete credentials, call CredentialsClient.delete():

CredentialManagerからはこの機能が削除されたようで、見当たりませんでした。ユーザーがGoogleパスワードマネージャーを通じて自分で削除することになりそうです。

CredentialManagerには clearCredentialState という関数が存在しますが、これはID/パスワードの削除とは関係ありませんでした。 ドキュメントを見ると、GoogleSignInなどの認証を利用した場合に、認証情報をクリアするために利用するもののようです。

Smart Lock for Passwords では指定したアプリとウェブサイト間で保存したパスワードを共有する仕組みがありましたが、CredentialManager でも動作します。設定方法は Smart Lock for Passwords と同じであり、移行に必要な作業はありません。

移行時の落とし穴

移行を試している際、落とし穴にはまりました。

事象

AndroidOS14以降で、パスワード保存・読み出しボトムシートが重複表示される。

重複表示される様子

1つ目の保存ボトムシートが出てから、2つ目の保存ボトムシートが出てきます。

原因

AndroidOS14以降では、オートフィルが強化され、Password入力のEditTextがあると、自動的にパスワード保存・読み出しUIが表示される。これはオートフィルの属性をいじっても無効化出来ない。
CredentialManagerで意図的にパスワード保存・読み出しをしていると、どちらも実行され、重複表示されてしまう。

解決方法

EditTextにisCredential=trueを付ける。
または、
Composeに移行する。

この落とし穴について、詳しくは下記資料をご覧ください。

speakerdeck.com

動作確認時に役立つパスワードマネージャーの使い方

開発や検証において、端末に保存したパスワードを管理したいことがあります。

  • 保存処理の確認のため、以前保存したパスワードを削除したい
  • 一度「保存しない」を選択すると、二度と保存確認が出ないので、出るようにしたい

これらを行うには、端末のパスワードマネージャーを操作します。

Googleパスワードマネージャー

パスワードマネージャーの開き方

パスワードマネージャーの開き方がいくつかあるので紹介します。
奥まったところにいるので、最初の「検索して開く」が一番簡単ですが、他の方法合わせて4つ紹介します。

A. 検索して開く

  1. 端末の設定アプリを開く
  2. 上部の検索窓に「パスワードマネージャー」と入力する
  3. パスワードマネージャーを選択する

B. Googleから開く

  1. 端末の設定アプリを開く
  2. Googleを選択
  3. 「すべてのサービス」タブを選択(ここで「推奨設定」タブにパスワードマネージャーが出てくる場合はそれを押せば完了)
  4. 自動入力 > Google自動入力 > Googleパスワードマネージャーを選択

C. パスワードとアカウントから開く

  1. 端末の設定アプリを開く
  2. 「パスワードとアカウント」を選択
  3. 自動入力サービスのGoogleの右側にある歯車を押す
  4. Googleパスワードマネージャーを選択

D. セキュリティとプライバシーから開く

  1. 端末の設定アプリを開く
  2. セキュリティとプライバシーを選択
  3. プライバシーの詳細設定を選択
  4. Googleの自動入力サービスを選択
  5. Googleパスワードマネージャーを選択

保存したパスワードを消す

Googleパスワードマネージャーから消すことが出来ます。

  1. Googleパスワードマネージャーを開く
  2. 「パスワード」タブ(初期タブ)にアプリ名が表示されるので、対象のアプリを選択する
  3. ロック解除が出たら解除する
  4. ここで削除や編集が出来る

パスワード編集画面

注意点として、Googleパスワードマネージャーは、端末に登録されているGoogleアカウント毎に設定が保存されています。 登録したはずなのに見つからない、といった場合は、アカウントが異なる可能性があります。
アカウントは右上のアカウントアイコンから変更できます。(Playストアでアカウントを切り替えるときと同じ方法です。)

「保存しない」を押した記録をリセットする

アプリでパスワードを保存するか聞かれた際、拒否した場合は二度と表示されなくなります。 再び検証でパスワード保存を使用したい場合に困りますが、この記録はリセットすることが出来ます。
これもGoogleパスワードマネージャーで行います。

  1. Googleパスワードマネージャーを開く
  2. 「設定」タブを開く
  3. 下にスクロールしていくと「不承認のサイトまたはアプリ」という項目がある
  4. そこにあるアプリの右側の×ボタンを押す

不承認のサイトまたはアプリ

これでリストからアプリを消すと、また次回から保存するか聞かれるようになります。

パスワードマネージャーをホーム画面に追加する

パスワードマネージャーを頻繁に利用する場合、ホーム画面に追加すると便利です。

  1. Googleパスワードマネージャーを開く
  2. 「設定」タブを開く
  3. 真ん中あたりにある「ホーム画面にショートカットを追加」をタップ

ホーム画面にショートカットを追加

余談:Autofill 機能と組み合わせた自動ログイン体験について

パスワードの提示タイミングとして主に二つ考えられます。

  1. ログイン画面起動時に自動提示
  2. ログインフォームタップ時に表示

1 は手間が少ないものの、唐突に出てくるため誤って消してしまう可能性があります。一方 2 は手入力を妨げないよう、一度表示したら次回以降のタップで表示しないようにするといった考慮が必要です。

1 の問題を解消するために、Autofill を組み合わせることが考えられます。これにより、

  • ログイン画面起動時は CredentialManager によりパスワードを提示
  • 誤って消した場合、ログインフォームをタップすると IME 側でパスワードを提示 (Autofill)

といった体験が実現できます。
ただし現状では、 Jetpack Compose における Autofill サポートは一部不完全であることがわかっており、現時点では EditText 等を用いるのが安心です。

一方で、執筆時点ではまだalphaバージョンであるcompose-ui 1.8には、alpha05から Autofill 周りの変更が入っており、今後の体験向上に期待しています。

おわりに

CredentialsApiからCredentialManagerに移行するために調べたことについて記載しました。
調べて実装を試す中で、CredentialManagerは直感的で使いやすい印象を受けました。

AutoFillについてはOS・レイアウトによって落とし穴がありましたが、無事解決することが出来ました。

パスワードマネージャーは、設定の奥まった部分にあり、たどり着き方も複数あり最初は迷いました。 設定の検索機能・ショートカット作成機能には助けられました。みなさんもパスワードマネージャーを使う際にはぜひ使ってみてください。

CredentialManagerでは、GoogleSignInやPasskeyなど、別の認証にも対応しているので、試してみたいと思いました。