From c21681747a72a75dfacb60d6f1a60df98d724dfc Mon Sep 17 00:00:00 2001 From: Aditya Wasan Date: Sun, 31 Dec 2023 18:25:55 -0500 Subject: feat: implement credential provider service for passkeys Signed-off-by: Aditya Wasan --- app/build.gradle.kts | 1 + passkeys/build.gradle.kts | 8 +- passkeys/lint-baseline.xml | 26 ++++ passkeys/src/main/AndroidManifest.xml | 29 ++-- .../passkeys/APSCredentialProviderService.kt | 103 +++++++++++++ .../main/res/drawable/ic_launcher_background.xml | 170 --------------------- .../main/res/drawable/ic_launcher_foreground.xml | 30 ---- .../src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 6 - .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 6 - passkeys/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../main/res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes passkeys/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../main/res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../src/main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes passkeys/src/main/res/values-night/themes.xml | 16 -- passkeys/src/main/res/values/colors.xml | 10 -- passkeys/src/main/res/values/strings.xml | 3 - passkeys/src/main/res/values/themes.xml | 16 -- passkeys/src/main/res/xml/provider.xml | 7 + 24 files changed, 157 insertions(+), 274 deletions(-) create mode 100644 passkeys/lint-baseline.xml create mode 100644 passkeys/src/main/java/app/passwordstore/passkeys/APSCredentialProviderService.kt delete mode 100644 passkeys/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 passkeys/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 passkeys/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 passkeys/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 passkeys/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 passkeys/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 passkeys/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 passkeys/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 passkeys/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 passkeys/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 passkeys/src/main/res/values-night/themes.xml delete mode 100644 passkeys/src/main/res/values/colors.xml delete mode 100644 passkeys/src/main/res/values/strings.xml delete mode 100644 passkeys/src/main/res/values/themes.xml create mode 100644 passkeys/src/main/res/xml/provider.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b6f0a378..ecf95133 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { implementation(projects.format.common) implementation(projects.passgen.diceware) implementation(projects.passgen.random) + implementation(projects.passkeys) implementation(projects.ui.compose) implementation(libs.androidx.activity) implementation(libs.androidx.activity.compose) diff --git a/passkeys/build.gradle.kts b/passkeys/build.gradle.kts index c2df2b85..7a69dadb 100644 --- a/passkeys/build.gradle.kts +++ b/passkeys/build.gradle.kts @@ -7,15 +7,10 @@ plugins { id("com.github.android-password-store.android-library") id("com.github.android-password-store.kotlin-android") - id("com.github.android-password-store.psl-plugin") } android { - defaultConfig { - minSdk = 23 - consumerProguardFiles("consumer-rules.pro") - } - sourceSets { getByName("test") { resources.srcDir("src/main/assets") } } + buildFeatures { androidResources = true } namespace = "app.passwordstore.passkeys" } @@ -23,7 +18,6 @@ dependencies { implementation(libs.androidx.annotation) implementation(libs.androidx.core.ktx) implementation(libs.androidx.credentials) - implementation(libs.androidx.credentials.play.services) implementation(libs.kotlinx.coroutines.core) implementation(libs.thirdparty.logcat) testImplementation(libs.bundles.testDependencies) diff --git a/passkeys/lint-baseline.xml b/passkeys/lint-baseline.xml new file mode 100644 index 00000000..aa3bc042 --- /dev/null +++ b/passkeys/lint-baseline.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/passkeys/src/main/AndroidManifest.xml b/passkeys/src/main/AndroidManifest.xml index 7a44af6e..0436b903 100644 --- a/passkeys/src/main/AndroidManifest.xml +++ b/passkeys/src/main/AndroidManifest.xml @@ -1,12 +1,21 @@ - + - - - + + + + + + + + \ No newline at end of file diff --git a/passkeys/src/main/java/app/passwordstore/passkeys/APSCredentialProviderService.kt b/passkeys/src/main/java/app/passwordstore/passkeys/APSCredentialProviderService.kt new file mode 100644 index 00000000..b9711a40 --- /dev/null +++ b/passkeys/src/main/java/app/passwordstore/passkeys/APSCredentialProviderService.kt @@ -0,0 +1,103 @@ +package app.passwordstore.passkeys + +import android.app.PendingIntent +import android.content.Intent +import android.os.Build +import android.os.CancellationSignal +import android.os.OutcomeReceiver +import androidx.annotation.RequiresApi +import androidx.credentials.exceptions.ClearCredentialException +import androidx.credentials.exceptions.CreateCredentialException +import androidx.credentials.exceptions.CreateCredentialUnknownException +import androidx.credentials.exceptions.GetCredentialException +import androidx.credentials.provider.BeginCreateCredentialRequest +import androidx.credentials.provider.BeginCreateCredentialResponse +import androidx.credentials.provider.BeginCreatePublicKeyCredentialRequest +import androidx.credentials.provider.BeginGetCredentialRequest +import androidx.credentials.provider.BeginGetCredentialResponse +import androidx.credentials.provider.CreateEntry +import androidx.credentials.provider.CredentialProviderService +import androidx.credentials.provider.ProviderClearCredentialStateRequest + +@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) +public class APSCredentialProviderService : CredentialProviderService() { + + override fun onBeginCreateCredentialRequest( + request: BeginCreateCredentialRequest, + cancellationSignal: CancellationSignal, + callback: OutcomeReceiver, + ) { + val response: BeginCreateCredentialResponse? = processCreateCredentialRequest(request) + if (response != null) { + callback.onResult(response) + } else { + callback.onError(CreateCredentialUnknownException()) + } + } + + override fun onBeginGetCredentialRequest( + request: BeginGetCredentialRequest, + cancellationSignal: CancellationSignal, + callback: OutcomeReceiver + ) {} + + override fun onClearCredentialStateRequest( + request: ProviderClearCredentialStateRequest, + cancellationSignal: CancellationSignal, + callback: OutcomeReceiver, + ) {} + + private fun processCreateCredentialRequest( + request: BeginCreateCredentialRequest + ): BeginCreateCredentialResponse? { + return when (request) { + is BeginCreatePublicKeyCredentialRequest -> { + // Request is passkey type + handleCreatePasskeyQuery(request) + } + // Request not supported + else -> null + } + } + + private fun handleCreatePasskeyQuery( + @Suppress("UNUSED_PARAMETER") request: BeginCreatePublicKeyCredentialRequest + ): BeginCreateCredentialResponse { + val createEntries: MutableList = mutableListOf() + println(request.requestJson) + createEntries.add( + CreateEntry( + DEFAULT_ACCOUNT_NAME, + createNewPendingIntent(DEFAULT_ACCOUNT_NAME, CREATE_PASSKEY_INTENT_ACTION) + ) + ) + + return BeginCreateCredentialResponse(createEntries) + } + + private fun createNewPendingIntent(accountId: String, action: String): PendingIntent { + val intent = Intent(action).setPackage(packageName) + // Add your local account ID as an extra to the intent, so that when + // user selects this entry, the credential can be saved to this + // account + intent.putExtra(EXTRA_KEY_ACCOUNT_ID, accountId) + + return PendingIntent.getActivity( + applicationContext, + REQUEST_CODE, + intent, + (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT), + ) + } + + internal companion object { + + // These intent actions are specified for corresponding activities + // that are to be invoked through the PendingIntent(s) + const val REQUEST_CODE = 1010101 + const val EXTRA_KEY_ACCOUNT_ID = "EXTRA_KEY_ACCOUNT_ID" + const val DEFAULT_ACCOUNT_NAME = "Default Password Store" + const val CREATE_PASSKEY_INTENT_ACTION = "app.passwordstore.CREATE_PASSKEY" + const val GET_PASSKEY_INTENT_ACTION = "PACKAGE_NAME.GET_PASSKEY" + } +} diff --git a/passkeys/src/main/res/drawable/ic_launcher_background.xml b/passkeys/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 140f8294..00000000 --- a/passkeys/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/passkeys/src/main/res/drawable/ic_launcher_foreground.xml b/passkeys/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 5c3bfcd6..00000000 --- a/passkeys/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 5ad9ce15..00000000 --- a/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 5ad9ce15..00000000 --- a/passkeys/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/passkeys/src/main/res/mipmap-hdpi/ic_launcher.webp b/passkeys/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78e..00000000 Binary files a/passkeys/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/passkeys/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d1..00000000 Binary files a/passkeys/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-mdpi/ic_launcher.webp b/passkeys/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d64..00000000 Binary files a/passkeys/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/passkeys/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611da..00000000 Binary files a/passkeys/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xhdpi/ic_launcher.webp b/passkeys/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a3070..00000000 Binary files a/passkeys/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/passkeys/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a6956..00000000 Binary files a/passkeys/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77f..00000000 Binary files a/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f508..00000000 Binary files a/passkeys/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d6427..00000000 Binary files a/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae37..00000000 Binary files a/passkeys/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/passkeys/src/main/res/values-night/themes.xml b/passkeys/src/main/res/values-night/themes.xml deleted file mode 100644 index f0a927fb..00000000 --- a/passkeys/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/passkeys/src/main/res/values/colors.xml b/passkeys/src/main/res/values/colors.xml deleted file mode 100644 index 09837df6..00000000 --- a/passkeys/src/main/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/passkeys/src/main/res/values/strings.xml b/passkeys/src/main/res/values/strings.xml deleted file mode 100644 index 485ed028..00000000 --- a/passkeys/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - passkeys - \ No newline at end of file diff --git a/passkeys/src/main/res/values/themes.xml b/passkeys/src/main/res/values/themes.xml deleted file mode 100644 index 4210ce7d..00000000 --- a/passkeys/src/main/res/values/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/passkeys/src/main/res/xml/provider.xml b/passkeys/src/main/res/xml/provider.xml new file mode 100644 index 00000000..99d41c9b --- /dev/null +++ b/passkeys/src/main/res/xml/provider.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file -- cgit v1.2.3