alphaが出たばかりなので、API等変更される可能性があります
新たなライブラリがリリースされた
2023年1月11日、androidx.credentials の1.0.0-alpha01 がリリースされました。
これはパスワードやパスキーなどを管理し、シームレスでセキュアなログイン体験を提供してくれるライブラリになっています。
本記事では実際にどういうことが可能かを試してみています。
関連クラス
CredentialManager
ユーザーの認証フローを管理するものです。
アプリはこのクラスにより、認証情報の登録や保存済みの認証情報の取得を、UIフローから利用することができます。
CredentialManager
は端末で利用できる CredentialProvider
に実際の処理を委譲します。
CredentialProvider
https://developer.android.com/reference/androidx/credentials/CredentialProvider
実際に認証情報の登録・取得処理を行っています。
これ自身はinterfaceで、OEMがライブラリなどとして実装することが想定されているようです。
ハードウェアメーカーが端末にセキュアに情報を保存する方法を提供するための方法ということでしょうか。
SDK version 33(Android 13)以下では開発者側はそのライブラリを依存に追加した上で、このインターフェースを実装するクラスをmeta-dataとして追加する必要があります。
SDK version 33より上では CredentialProvider
の提供者はフレームワークに直接登録する形となるようです。
実装する
では実際に使ってみましょう。
依存関係
まずは依存関係に androidx.credentials
を追加します。
実際に CredentialProvider
の実装がなければ使えないので、現状使える credentials-play-ervices-auth
も追加します。
dependencies {
implementation 'androidx.credentials:credentials:1.0.0-alpha01'
implementation 'androidx.credentials:credentials-play-services-auth:1.0.0-alpha01'
}
AndroidManifest
AndroidManifest
には、どの CredentialProvider
を使うかを登録します。
今回はPlayServiceのもの(Googleのパスワードマネージャー)を表すCredentialProviderPlayServicesImpl
を指定します。
<service android:name="androidx.credentials.playservices.CredentialProviderMetadataHolder">
<meta-data
android:name="androidx.credentials.CREDENTIAL_PROVIDER_KEY"
android:value="androidx.credentials.playservices.CredentialProviderPlayServicesImpl" />
</service>
追記: CredentialProviderMetadataHolder
の宣言はライブラリ側のAndroidManifestで行われています。
つまり androidx.credentials:credentials-play-services-auth
が入っていれば勝手にAndroidManifestにマージされるため、自前で書く必要はありません。
認証情報登録
認証情報の登録は CredentialManager#executeCreateCredential()
で行います。
id/パスワードが空文字だと例外が出るので注意します。
またUIを使ったフロー中にキャンセルされると例外が出るので処理します。
lifecycleScope.launch {
if(id.isNullOrEmpty() || password.isNullOrEmpty()) return@launch
val request = CreatePasswordRequest(id, password)
val credentialManager = CredentialManager.create(this)
try {
credentialManager.executeCreateCredential(request, this@CredentialActivity)
} catch (e: CreateCredentialCancellationException) {
Toast.makeText(this@CredentialActivity, "キャンセルされました", Toast.LENGTH_LONG).show()
}
}
認証情報取得
認証情報の取得は CredentialManager#executeGetCredential()
で行います。
認証情報は Bundle
に入ってきますので、 PasswordCredential.BUNDLE_KEY_ID
PasswordCredential.BUNDLE_KEY_PASSWORD
で取得します。
また以下のケースで例外が投げられるのでこちらも処理します。
-
GetCredentialCancellationException
- UI上で閉じるボタンを押すなどキャンセルされた場合
-
GetCredentialInterruptedException
- このアプリに紐づく認証情報が保存されていない場合
lifecycleScope.launch {
val text = try {
val request = GetCredentialRequest(listOf(GetPasswordOption()))
val response = credentialManager.executeGetCredential(request, this@CredentialActivity)
val credential = response.credential
val id = credential.data.getString(PasswordCredential.BUNDLE_KEY_ID, "")
val password = credential.data.getString(PasswordCredential.BUNDLE_KEY_PASSWORD, "")
"id: $id pass: $password"
} catch (e: GetCredentialCancellationException) {
"キャンセルされました"
} catch (e: GetCredentialInterruptedException) {
"エラーが発生しました"
}
Toast.makeText(this@CredentialActivity, text, Toast.LENGTH_LONG).show()
}
完成
実際にUIも含めて作ったのがこちら。
https://github.com/verno3632/WorkingDog/tree/main/credential
認証情報保存の際に、Googleのパスワードマネージャーに登録されます。
パスワードマネージャーを覗いてみると、アプリのパッケージ名(アプリケーションID)で保存されていました。
もちろん端末を跨いで共有することが出来ます。
終わりに
まだ1.0.0-alpha01ということで、絶賛開発中のようです。コード中にもTODOの部分が多くありました。
33以下では認証情報管理のライブラリを明示的に依存関係に追加しなければいけませんが、34以上では扱いが違うようなことがドキュメントから読み取れます。
34以上で端末で利用できるパスワードマネージャーからユーザーが好きに選択して使えるとかになるなど、Androidへの機能追加があるんじゃないか?と思ってます。
今後とも注視していきたいですね