diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerImpl.kt b/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerImpl.kt index 1f6ff9d545..ee73aa9123 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerImpl.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerImpl.kt @@ -20,6 +20,7 @@ import com.bitwarden.fido.Fido2CredentialAutofillView import com.bitwarden.fido.Origin import com.bitwarden.fido.UnverifiedAssetLink import com.bitwarden.sdk.Fido2CredentialStore +import com.bitwarden.ui.platform.base.util.prefixHttpsIfNecessary import com.bitwarden.ui.platform.base.util.prefixHttpsIfNecessaryOrNull import com.bitwarden.ui.platform.base.util.toAndroidAppUriString import com.bitwarden.vault.CipherListView @@ -343,7 +344,16 @@ class BitwardenCredentialManagerImpl( ?.let { ClientData.DefaultWithCustomHash(hash = it) } ?: return Fido2RegisterCredentialResult.Error.InvalidAppSignature - val sdkOrigin = createPublicKeyCredentialRequest.origin + val requestedOrigin = this + .getPasskeyAttestationOptionsOrNull(createPublicKeyCredentialRequest.requestJson) + ?.relyingParty + ?.id + ?.prefixHttpsIfNecessary() + + // PM-35130: We use the requested relying party for the basis of the origin for privileged + // apps to ensure that related-origin requests are processed successfully. In the future, + // the SDK should handle this for us and we will be able to send in the real origin. + val sdkOrigin = (requestedOrigin ?: createPublicKeyCredentialRequest.origin) ?.let { Origin.Web(it) } ?: return Fido2RegisterCredentialResult.Error.MissingHostUrl diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerTest.kt index 5f2974640d..13c88bc8c6 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/data/credentials/manager/BitwardenCredentialManagerTest.kt @@ -512,9 +512,10 @@ class BitwardenCredentialManagerTest { @Suppress("MaxLineLength") @Test - fun `registerFido2Credential should return MissingHostUrl when calling app if privileged and origin is missing`() = + fun `registerFido2Credential should return MissingHostUrl when calling app if privileged and relying party and origin are missing`() = runTest { every { mockCreatePublicKeyCredentialRequest.origin } returns null + every { json.decodeFromStringOrNull(any()) } returns null val result = bitwardenCredentialManager.registerFido2Credential( userId = "mockUserId", @@ -1503,7 +1504,7 @@ private val DEFAULT_ANDROID_ORIGIN = Origin.Android( assetLinkUrl = "https://$DEFAULT_HOST/.well-known/assetlinks.json", ), ) -private val DEFAULT_WEB_ORIGIN = Origin.Web("bitwarden.com") +private val DEFAULT_WEB_ORIGIN = Origin.Web("https://bitwarden.com") private const val DEFAULT_FIDO2_AUTH_REQUEST_JSON = """ { "allowCredentials": [], diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/util/PasskeyAttestationOptionsTestHelpers.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/util/PasskeyAttestationOptionsTestHelpers.kt index ca96b181e1..099ebd8430 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/util/PasskeyAttestationOptionsTestHelpers.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/addedit/util/PasskeyAttestationOptionsTestHelpers.kt @@ -8,15 +8,15 @@ import com.x8bit.bitwarden.data.credentials.model.UserVerificationRequirement * Returns a mock FIDO 2 [PasskeyAttestationOptions] object to simulate a credential * creation request. */ -@Suppress("MaxLineLength") fun createMockPasskeyAttestationOptions( number: Int, userVerificationRequirement: UserVerificationRequirement = UserVerificationRequirement.PREFERRED, relyingPartyId: String = "mockPublicKeyCredentialRpEntity-$number", -) = PasskeyAttestationOptions( - authenticatorSelection = PasskeyAttestationOptions - .AuthenticatorSelectionCriteria(userVerification = userVerificationRequirement), +): PasskeyAttestationOptions = PasskeyAttestationOptions( + authenticatorSelection = PasskeyAttestationOptions.AuthenticatorSelectionCriteria( + userVerification = userVerificationRequirement, + ), challenge = "mockPublicKeyCredentialCreationOptionsChallenge-$number", excludeCredentials = listOf( PublicKeyCredentialDescriptor(