Skip to content

Commit

Permalink
PasswordIntentUtils according to Fido2IntentUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
Nailik committed Oct 19, 2024
1 parent 5321cda commit c2aaf28
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.x8bit.bitwarden.data.autofill.password.model

import android.content.pm.SigningInfo
import android.os.Parcelable
import androidx.credentials.provider.CallingAppInfo
import kotlinx.parcelize.Parcelize

/**
* Models a FIDO 2 credential authentication request parsed from the launching intent.
*/
@Parcelize
data class PasswordCredentialAssertionRequest(
val userId: String,
val cipherId: String?,
val credentialId: String?,
val allowedUserIds: Set<String>,
val isAutoSelectAllowed: Boolean,
val packageName: String,
val signingInfo: SigningInfo,
val origin: String?,
) : Parcelable {
val callingAppInfo: CallingAppInfo
get() = CallingAppInfo(packageName, signingInfo, origin)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.x8bit.bitwarden.data.autofill.password.model

import android.content.pm.SigningInfo
import android.os.Parcelable
import androidx.credentials.provider.CallingAppInfo
import kotlinx.parcelize.Parcelize

/**
* Represents raw data from the a user deciding to create a password in their vault via the
* credential manager framework.
*
* @property userId The user under which the passkey should be saved.
* @property password containing the Password request.
* @property callingAppInfo Information about the application that initiated the request.
*/
@Parcelize
data class PasswordCredentialRequest(
val userId: String,
val password: String,
val packageName: String,
val signingInfo: SigningInfo,
val origin: String?,
) : Parcelable {
val callingAppInfo: CallingAppInfo
get() = CallingAppInfo(
packageName = packageName,
signingInfo = signingInfo,
origin = origin,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.x8bit.bitwarden.data.autofill.password.model

import android.content.pm.SigningInfo
import android.os.Bundle
import android.os.Parcelable
import androidx.credentials.provider.BeginGetPasswordOption
import androidx.credentials.provider.CallingAppInfo
import kotlinx.parcelize.Parcelize

/**
* Models a FIDO 2 request to retrieve FIDO credentials parsed from the launching intent.
*/
@Parcelize
data class PasswordGetCredentialsRequest(
val candidateQueryData: Bundle,
val id: String,
val userId: String,
val allowedUserIds: Set<String>,
val packageName: String,
val signingInfo: SigningInfo,
val origin: String?,
) : Parcelable {
val callingAppInfo: CallingAppInfo
get() = CallingAppInfo(packageName, signingInfo, origin)

val option: BeginGetPasswordOption
get() = BeginGetPasswordOption(
allowedUserIds,
candidateQueryData,
id,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.x8bit.bitwarden.data.autofill.password.util

import android.content.Intent
import android.os.Build
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.provider.BeginGetPasswordOption
import androidx.credentials.provider.PendingIntentHandler
import com.x8bit.bitwarden.data.autofill.password.model.PasswordCredentialAssertionRequest
import com.x8bit.bitwarden.data.autofill.password.model.PasswordCredentialRequest
import com.x8bit.bitwarden.data.autofill.password.model.PasswordGetCredentialsRequest
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CIPHER_ID
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_CREDENTIAL_ID
import com.x8bit.bitwarden.ui.platform.manager.intent.EXTRA_KEY_USER_ID

/**
* Checks if this [Intent] contains a [PasswordCredentialRequest] related to an ongoing FIDO 2
* credential creation process.
*/
fun Intent.getPasswordCredentialRequestOrNull(): PasswordCredentialRequest? {
if (isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return null

val systemRequest = PendingIntentHandler
.retrieveProviderCreateCredentialRequest(this)
?: return null

val createPublicKeyRequest = systemRequest
.callingRequest
as? CreatePasswordRequest
?: return null

val userId = getStringExtra(EXTRA_KEY_USER_ID)
?: return null

return PasswordCredentialRequest(
userId = userId,
password = createPublicKeyRequest.password,
packageName = systemRequest.callingAppInfo.packageName,
signingInfo = systemRequest.callingAppInfo.signingInfo,
origin = systemRequest.callingAppInfo.origin,
)
}

/**
* Checks if this [Intent] contains a [PasswordCredentialAssertionRequest] related to an ongoing Password
* credential authentication process.
*/
fun Intent.getPasswordAssertionRequestOrNull(): PasswordCredentialAssertionRequest? {
if (isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return null

val systemRequest = PendingIntentHandler
.retrieveProviderGetCredentialRequest(this)
?: return null

val option: GetPasswordOption = systemRequest
.credentialOptions
.firstNotNullOfOrNull { it as? GetPasswordOption }
?: return null

val credentialId = getStringExtra(EXTRA_KEY_CREDENTIAL_ID)
?: return null

val cipherId = getStringExtra(EXTRA_KEY_CIPHER_ID)
?: return null

val userId: String = getStringExtra(EXTRA_KEY_USER_ID)
?: return null

return PasswordCredentialAssertionRequest(
userId = userId,
cipherId = cipherId,
credentialId = credentialId,
allowedUserIds = option.allowedUserIds,
isAutoSelectAllowed = option.isAutoSelectAllowed,
packageName = systemRequest.callingAppInfo.packageName,
signingInfo = systemRequest.callingAppInfo.signingInfo,
origin = systemRequest.callingAppInfo.origin,
)
}

/**
* Checks if this [Intent] contains a [PasswordGetCredentialsRequest] related to an ongoing FIDO 2
* credential lookup process.
*/
fun Intent.getPasswordGetCredentialsRequestOrNull(): PasswordGetCredentialsRequest? {
if (isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return null

val systemRequest = PendingIntentHandler
.retrieveBeginGetCredentialRequest(this)
?: return null

val option: BeginGetPasswordOption = systemRequest
.beginGetCredentialOptions
.firstNotNullOfOrNull { it as? BeginGetPasswordOption }
?: return null

val callingAppInfo = systemRequest
.callingAppInfo
?: return null

val userId: String = getStringExtra(EXTRA_KEY_USER_ID)
?: return null

return PasswordGetCredentialsRequest(
candidateQueryData = option.candidateQueryData,
id = option.id,
userId = userId,
allowedUserIds = option.allowedUserIds,
packageName = callingAppInfo.packageName,
signingInfo = callingAppInfo.signingInfo,
origin = callingAppInfo.origin,
)
}

0 comments on commit c2aaf28

Please sign in to comment.