Skip to content

[PM-11886] Update handling of unprivileged apps and improve error messaging #4694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 12, 2025

Conversation

SaintPatrck
Copy link
Contributor

@SaintPatrck SaintPatrck commented Feb 4, 2025

🎟️ Tracking

PM-11886
Resolves #4239

📔 Objective

Improve passkey processing with unprivileged applications and provide more descriptive error messages when failures occur.

📸 Screenshots

Coming soon!

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed
    issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@SaintPatrck SaintPatrck added help wanted hold do not merge yet labels Feb 4, 2025
Copy link
Contributor

github-actions bot commented Feb 4, 2025

Logo
Checkmarx One – Scan Summary & Details93623026-9306-443a-85f9-8cc19ec5a9a7

Fixed Issues (7)

Great job! The following issues were fixed in this Pull Request

Severity Issue Source File / Package
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 829
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 1199
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 1199
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 828
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 1199
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 1199
MEDIUM Privacy_Violation /app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/itemlisting/VaultItemListingViewModel.kt: 1199

@SaintPatrck SaintPatrck force-pushed the PM-11886/update-origin-for-unprivileged-apps branch from 5ddfd15 to dd31e4f Compare February 4, 2025 23:31
@BJReplay
Copy link

BJReplay commented Feb 5, 2025

Ahh, no luck - it looks like there isn't a build for that. @SaintPatrck are you able to run a build, so I can install the build artifact? I don't think I have the ability to set up a build environment on my own.

https://github.com/bitwarden/android/actions/runs/13147380497/job/36688357537?pr=4694 failed.

@SaintPatrck SaintPatrck force-pushed the PM-11886/update-origin-for-unprivileged-apps branch from 84abd71 to 962de84 Compare February 5, 2025 02:45
Copy link

codecov bot commented Feb 5, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.42%. Comparing base (00f30c9) to head (232c642).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4694      +/-   ##
==========================================
+ Coverage   89.40%   89.42%   +0.01%     
==========================================
  Files         490      490              
  Lines       40980    41020      +40     
  Branches     5836     5823      -13     
==========================================
+ Hits        36638    36681      +43     
+ Misses       2321     2318       -3     
  Partials     2021     2021              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@BJReplay
Copy link

BJReplay commented Feb 5, 2025

Thanks! Watching the build now.

@SaintPatrck
Copy link
Contributor Author

@BJReplay builds are available: https://github.com/bitwarden/android/actions/runs/13149534226#artifacts

@BJReplay
Copy link

BJReplay commented Feb 5, 2025

@BJReplay builds are available: https://github.com/bitwarden/android/actions/runs/13149534226#artifacts

Thanks for the heads up.

Will install and test now.

@SaintPatrck SaintPatrck force-pushed the PM-11886/update-origin-for-unprivileged-apps branch from 24e174e to 89e7e99 Compare February 5, 2025 21:46
This commit introduces the ability to copy Passkey logs for debugging purposes.

Key changes:

-   Added `writeToFile` and `readFromFile` functions to `FileManager` to handle file writing and reading operations.
-   Implemented `getPasskeyLogs` function in `LogsManager` to fetch the logs.
-   Introduced a PasskeyTree class in `LogsManagerImpl` to write Passkey related logs to a designated log file.
-   Added a "Copy passkey logs" option in the About screen to allow users to copy the logs to the clipboard.
-   Updated `AboutViewModel` to handle the copy passkey logs action.
@SaintPatrck SaintPatrck force-pushed the PM-11886/update-origin-for-unprivileged-apps branch from 89e7e99 to d9601b3 Compare February 5, 2025 22:19
@SaintPatrck
Copy link
Contributor Author

@BJReplay I've added logs and a couple ways to capture the ones that would help nail this down.

  1. Logcat - If you have the Android SDK tools installed, plug in your device, startup logcat, and filter for the tag "PASSKEY".
  2. Copy logs from About screen - Logs with the "PASSKEY" tag are written to disk. If you navigate to Settings > About you will see a new button, "Copy passkey logs". Clicking it will copy the logs to your clipboard for easy pasting.

The updated builds will be available here: https://github.com/bitwarden/android/actions/runs/13167643578

Feel free to paste those logs here or package them in a Send. No data is logged. Only call path indicators so I can track where the generic errors are spawning.

Thanks again for all of the assistance with hunting this down. I really appreciate you taking the time. 🫶

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

The updated builds will be available here: https://github.com/bitwarden/android/actions/runs/13167643578

@SaintPatrck do I need a specific version (beta? dev?)?

I'm trying beta because that's how I'm running native alongside legacy, but with a test run against webauthn.io it doesn't appear to be capturing anything.

The copied log from the About screen simply says Log file does not exist and the logcat logs don't contain any lines with PASSKEY

PS C:\Users\BJReplay> adb shell pidof 'com.x8bit.bitwarden.beta'
29549
PS C:\Users\BJReplay> adb logcat --pid=29549 PASSKEY >> passkey.log

Even running without the filterspec doesn't seem to log any lines:

PS C:\Users\BJReplay> adb shell pidof 'com.x8bit.bitwarden.beta'
29549
PS C:\Users\BJReplay> adb logcat --pid=29549 >> passkey.log

@SaintPatrck
Copy link
Contributor Author

@BJReplay Ah, I forgot to mention logcat output is only enabled on the dev builds. The copy button is available on all of the variants.

Also, logs are only emitted when failures occur. If everything works as expected on our end the file will be empty or not exist.

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

Also, logs are only emitted when failures occur.

Aha, that's why nothing was captured with my first test to test that I was capturing - it was a successful test!

Back to it...

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

Ok, no luck, @SaintPatrck

I could get

© Bitwarden Inc. 2015-2025

Version: 2025.2.0 (19778)
📱 samsung SM-S908E 🤖 14@34 📦 beta
🧱 commit: d9601b3
💻 build source: bitwarden/android/actions/runs/13167643578/attempts/1

to respond to passkey login attempts on:

However, when I started Ubank, it would only list the passkey stored in Bitwarden legacy and Keyguard.

It would not list Bitwarden native.

I set the passkey settings in the OS to only have Bitwarden native.

At this point I could still log in to

However, when I attempt to log into Ubank, I get a message (from Ubank):

image
Something went wrong!
Something seems to have gone wrong.
Please try again.
OK

It looks like these changes should not prevent the passkey from being offered, but it looks like, for some reason, this is a regression to an earlier version of this bug where Bitwarden native simply won't offer the passkey.

All test so far with beta - documenting now, and will soon try dev, just in case.

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

@SaintPatrck got there in the end.

Bizarrely, once I'd installed Dev, and set it up as preferred, Beta suddenly showed up for Ubank (but Dev did not).

Logs were pretty simple - hope this helps - let me know if you want me to try to get Dev working for a logcat capture.

[2025-02-06 12:38:42] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.
[2025-02-06 12:38:45] PASSKEY	A  handleDismissFido2ErrorDialogClick but no FIDO2 request found.

@SaintPatrck
Copy link
Contributor Author

SaintPatrck commented Feb 6, 2025

@BJReplay Nice! We're getting here, but we're not able to parse the relyingPartyId which is required to verify the authenticity of the request and to find the correct credential(s) for selection.

I'm going to add another log to capture the full request. Nothing in this request is compromising, but feel free to scrub the challenge and userId before posting if it makes you more comfortable. The most important thing we need is rpId from the requestJson. I've confirmed all passkey operations work with the Kayak app. For comparison, below is an example of their GetCredentials request that we receive.

Fido2GetCredentialsRequest(
  candidateQueryData=Bundle
  [
    {
      androidx.credentials.BUNDLE_KEY_REQUEST_JSON=
        {
          "allowCredentials":[],
          "challenge":"----",
          "rpId":"www.kayak.com"
        },
      androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, 
      androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100,
      android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=4ec32598-d307-439c-82fb-6bd103801b31,
      androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION,
      androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true
    }
  ],
  id=4ec32598-d307-439c-82fb-6bd103801b31,
  userId=8e011726-xxxx-xxxx-xxxx-b1d901389de9,
  requestJson={
    "allowCredentials":[],
    "challenge":"----",
    "rpId":"www.kayak.com"
  },
  clientDataHash=null,
  packageName=com.kayak.android,
  signingInfo=android.content.pm.SigningInfo@15e3677,
  origin=null
)

@SaintPatrck
Copy link
Contributor Author

Testable builds will be available here: https://github.com/bitwarden/android/actions/runs/13187375689

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

Will do - may not be until late today - have a lot on today.

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

Currently working remotely, so no USB cable, and no adb logcat possible.

One of the issues I have testing (on a S22U) is that it seems really hard to get Passkey and Preferred Passkey settings to stick, and nominated apps to present passkeys on a login prompt.

So, this login attempt I managed to get KeyGuard to present, and...

This is the error message that popped up on KeyGuard

Screenshot_20250207_092230_Keyguard

I don't know if that's because I've invalidated the passkey at UBank with all my cancelled login attempts (possible - I won't know until I successfully log in), but the error message felt like it was worth sharing as a hint.

Will continue to test as possible.

@BJReplay
Copy link

BJReplay commented Feb 6, 2025

OK, @SaintPatrck finally got there after a couple of reboots and countless changing of auto-fill and passkey settings.

Logs below.

First logs are yesterday.

I added a blank line to separate them.

Second logs are today.

Note that there are three different public keys, each repeated in two places.

I've redacted all information that might be sensitive. The redactions are <bracketed> like so, with the <> indicating the exact start and end of redactions. Quotes are left as quotes. Unquoted data is left as unquoted.

[2025-02-06 12:38:42] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.
[2025-02-06 12:38:45] PASSKEY	A  handleDismissFido2ErrorDialogClick but no FIDO2 request found.

[2025-02-07 09:52:16] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.
[2025-02-07 09:52:16] PASSKEY	D  vaultLoadedReceive called with GetCredentialsRequest=Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<Challenge Present but REDACTED>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"<Public Key 1 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 2 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 3 Present but REDACTED>"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<Bundle ID Present but REDACTED>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<Bundle ID Present but REDACTED>, userId=<User ID Present but REDACTED>, requestJson={"challenge":"<Challenge Present but REDACTED>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"<Public Key 1 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 2 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 3 Present but REDACTED>"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@a1d0903, origin=null)
[2025-02-07 09:52:19] PASSKEY	A  handleDismissFido2ErrorDialogClick but no FIDO2 request found.

JSON extracted:

{"challenge":"<Challenge Present but REDACTED>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"<Public Key 1 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 2 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 3 Present but REDACTED>"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<Bundle ID Present but REDACTED>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<Bundle ID Present but REDACTED>, userId=<User ID Present but REDACTED>, requestJson={"challenge":"<Challenge Present but REDACTED>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"<Public Key 1 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 2 Present but REDACTED>"},{"type":"public-key","id":"<Public Key 3 Present but REDACTED>"}],"userVerification":"required"}

- In `Fido2ProviderProcessorImpl.kt`, log the received create credential request and get credential request, including the calling app's package name and the request data.
- In `Fido2IntentUtils.kt`, log the created `Fido2CreateCredentialRequest`, `Fido2CredentialAssertionRequest`, and `Fido2GetCredentialsRequest`.
@SaintPatrck SaintPatrck force-pushed the PM-11886/update-origin-for-unprivileged-apps branch from 7d2de8f to 95e1bfd Compare February 11, 2025 23:25
@BJReplay
Copy link

Yes, it is. It only adds a few more logs.

I tested the build before this comment - I have been on a call, and had downloaded them prior to the call, but only just installed.

I haven't yet installed the latest build.

From that earlier build (dev). Note one successful warm up to make sure that dev was responding to passkeys at passkeys.io is also logged.

[2025-02-12 11:40:39] PASSKEY	D  processGetCredentialRequest received from package com.microsoft.emmx with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"allowCredentials":[],"challenge":"<redacted>","rpId":"www.passkeys.io","userVerification":"preferred"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=[<redacted>], android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=false, com.android.chrome.INCOGNITO=false, com.android.chrome.GPM_IGNORE=false, com.android.chrome.CHANNEL=stable}]
[2025-02-12 11:40:39] PASSKEY	D  processGetCredentialRequest received from package com.microsoft.emmx with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"allowCredentials":[],"challenge":"<redacted>","rpId":"www.passkeys.io","userVerification":"preferred"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=[<redacted>], android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=false, com.android.chrome.INCOGNITO=false, com.android.chrome.GPM_IGNORE=false, com.android.chrome.CHANNEL=stable}]

[2025-02-12 11:41:06] PASSKEY	D  processGetCredentialRequest received from package au.com.bank86400 with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=842fdba5-1043-4a3a-814e-a425aaf9eebd, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}]
[2025-02-12 11:41:10] PASSKEY	D  getFido2GetCredentialsRequestOrNull returned request: Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@7fdca61, origin=null)
[2025-02-12 11:41:14] PASSKEY	D  vaultLoadedReceive called with GetCredentialsRequest=Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"<redacted>"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@7fdca61, origin=null)
[2025-02-12 11:41:14] PASSKEY	E  Failed to decode passkey assertion options: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:95)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:168)
	at kotlinx.serialization.encoding.CompositeDecoder.decodeSerializableElement$default(Decoding.kt:539)
	at kotlinx.serialization.internal.CollectionLikeSerializer.readElement(CollectionSerializers.kt:80)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
	at com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManagerImpl.getPasskeyAssertionOptionsOrNull(Fido2CredentialManagerImpl.kt:264)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.vaultLoadedReceive(VaultItemListingViewModel.kt:1374)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleVaultDataReceive(VaultItemListingViewModel.kt:1139)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleInternalAction(VaultItemListingViewModel.kt:1012)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:272)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel$1$1.emit(BaseViewModel.kt:58)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:33)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.access$emitAllImpl$FlowKt__ChannelsKt(Channels.kt:1)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(Unknown Source:14)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:233)
	at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:175)
	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:147)
	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:470)
	at kotlinx.coroutines.CancellableContinuationImpl.completeResume(CancellableContinuationImpl.kt:591)
	at kotlinx.coroutines.channels.BufferedChannelKt.tryResume0(BufferedChannel.kt:2957)
	at kotlinx.coroutines.channels.BufferedChannelKt.access$tryResume0(BufferedChannel.kt:1)
	at kotlinx.coroutines.channels.BufferedChannel$BufferedChannelIterator.tryResumeHasNext(BufferedChannel.kt:1719)
	at kotlinx.coroutines.channels.BufferedChannel.tryResumeReceiver(BufferedChannel.kt:662)
	at kotlinx.coroutines.channels.BufferedChannel.updateCellSend(BufferedChannel.kt:478)
	at kotlinx.coroutines.channels.BufferedChannel.access$updateCellSend(BufferedChannel.kt:33)
	at kotlinx.coroutines.channels.BufferedChannel.send$suspendImpl(BufferedChannel.kt:3150)
	at kotlinx.coroutines.channels.BufferedChannel.send(Unknown Source:0)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel.sendAction(BaseViewModel.kt:82)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.access$sendAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:50)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$$inlined$map$1$2.emit(Emitters.kt:50)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$$inlined$map$1$2$1.invokeSuspend(Unknown Source:15)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:35)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:101)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:230)
	at android.os.Looper.loop(Looper.java:319)
	at android.app.ActivityThread.main(ActivityThread.java:9063)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing
	at kotlinx.serialization.internal.PluginExceptionsKt.throwMissingFieldException(PluginExceptions.kt:20)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor.<init>(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	... 59 more

[2025-02-12 11:41:14] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.
[2025-02-12 11:41:15] PASSKEY	A  handleDismissFido2ErrorDialogClick but no FIDO2 request found.
[2025-02-12 11:41:32] PASSKEY	D  getFido2GetCredentialsRequestOrNull returned request: Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"<redacted>"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@328f859, origin=null)
[2025-02-12 11:41:34] PASSKEY	D  vaultLoadedReceive called with GetCredentialsRequest=Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@328f859, origin=null)
[2025-02-12 11:41:34] PASSKEY	E  Failed to decode passkey assertion options: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:95)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:168)
	at kotlinx.serialization.encoding.CompositeDecoder.decodeSerializableElement$default(Decoding.kt:539)
	at kotlinx.serialization.internal.CollectionLikeSerializer.readElement(CollectionSerializers.kt:80)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
	at com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManagerImpl.getPasskeyAssertionOptionsOrNull(Fido2CredentialManagerImpl.kt:264)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.vaultLoadedReceive(VaultItemListingViewModel.kt:1374)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleVaultDataReceive(VaultItemListingViewModel.kt:1139)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleInternalAction(VaultItemListingViewModel.kt:1012)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:272)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel$1$1.emit(BaseViewModel.kt:58)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:33)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.access$emitAllImpl$FlowKt__ChannelsKt(Channels.kt:1)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(Unknown Source:14)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:233)
	at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:175)
	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:147)
	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:470)
	at kotlinx.coroutines.CancellableContinuationImpl.completeResume(CancellableContinuationImpl.kt:591)
	at kotlinx.coroutines.channels.BufferedChannelKt.tryResume0(BufferedChannel.kt:2957)
	at kotlinx.coroutines.channels.BufferedChannelKt.access$tryResume0(BufferedChannel.kt:1)
	at kotlinx.coroutines.channels.BufferedChannel$BufferedChannelIterator.tryResumeHasNext(BufferedChannel.kt:1719)
	at kotlinx.coroutines.channels.BufferedChannel.tryResumeReceiver(BufferedChannel.kt:662)
	at kotlinx.coroutines.channels.BufferedChannel.updateCellSend(BufferedChannel.kt:478)
	at kotlinx.coroutines.channels.BufferedChannel.access$updateCellSend(BufferedChannel.kt:33)
	at kotlinx.coroutines.channels.BufferedChannel.send$suspendImpl(BufferedChannel.kt:3150)
	at kotlinx.coroutines.channels.BufferedChannel.send(Unknown Source:0)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel.sendAction(BaseViewModel.kt:82)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.access$sendAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:50)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$$inlined$map$1$2.emit(Emitters.kt:50)
	at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:401)
	at kotlinx.coroutines.flow.StateFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:230)
	at android.os.Looper.loop(Looper.java:319)
	at android.app.ActivityThread.main(ActivityThread.java:9063)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing
	at kotlinx.serialization.internal.PluginExceptionsKt.throwMissingFieldException(PluginExceptions.kt:20)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor.<init>(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	... 57 more

[2025-02-12 11:41:34] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.
[2025-02-12 11:41:35] PASSKEY	A  handleDismissFido2ErrorDialogClick but no FIDO2 request found.

@BJReplay
Copy link

More logs - from latest build. dev.apk

[2025-02-12 12:16:17] PASSKEY	D  processGetCredentialRequest received from package au.com.bank86400 with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}]
[2025-02-12 12:16:20] PASSKEY	D  getFido2GetCredentialsRequestOrNull returned request: Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@284bd5d, origin=null)
[2025-02-12 12:16:23] PASSKEY	D  vaultLoadedReceive called with GetCredentialsRequest=Fido2GetCredentialsRequest(candidateQueryData=Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}], id=<redacted>, userId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@284bd5d, origin=null)
[2025-02-12 12:16:23] PASSKEY	E  Failed to decode passkey assertion options: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing at path: $.allowCredentials[0]
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:95)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableElement(StreamingJsonDecoder.kt:168)
	at kotlinx.serialization.encoding.CompositeDecoder.decodeSerializableElement$default(Decoding.kt:539)
	at kotlinx.serialization.internal.CollectionLikeSerializer.readElement(CollectionSerializers.kt:80)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
	at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:78)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions$$serializer.deserialize(PasskeyAssertionOptions.kt:10)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
	at com.x8bit.bitwarden.data.autofill.fido2.manager.Fido2CredentialManagerImpl.getPasskeyAssertionOptionsOrNull(Fido2CredentialManagerImpl.kt:264)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.vaultLoadedReceive(VaultItemListingViewModel.kt:1384)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleVaultDataReceive(VaultItemListingViewModel.kt:1149)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleInternalAction(VaultItemListingViewModel.kt:1022)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:272)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.handleAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel$1$1.emit(BaseViewModel.kt:58)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:33)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt.access$emitAllImpl$FlowKt__ChannelsKt(Channels.kt:1)
	at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(Unknown Source:14)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:233)
	at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:175)
	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:147)
	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:470)
	at kotlinx.coroutines.CancellableContinuationImpl.completeResume(CancellableContinuationImpl.kt:591)
	at kotlinx.coroutines.channels.BufferedChannelKt.tryResume0(BufferedChannel.kt:2957)
	at kotlinx.coroutines.channels.BufferedChannelKt.access$tryResume0(BufferedChannel.kt:1)
	at kotlinx.coroutines.channels.BufferedChannel$BufferedChannelIterator.tryResumeHasNext(BufferedChannel.kt:1719)
	at kotlinx.coroutines.channels.BufferedChannel.tryResumeReceiver(BufferedChannel.kt:662)
	at kotlinx.coroutines.channels.BufferedChannel.updateCellSend(BufferedChannel.kt:478)
	at kotlinx.coroutines.channels.BufferedChannel.access$updateCellSend(BufferedChannel.kt:33)
	at kotlinx.coroutines.channels.BufferedChannel.send$suspendImpl(BufferedChannel.kt:3150)
	at kotlinx.coroutines.channels.BufferedChannel.send(Unknown Source:0)
	at com.x8bit.bitwarden.ui.platform.base.BaseViewModel.sendAction(BaseViewModel.kt:82)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel.access$sendAction(VaultItemListingViewModel.kt:94)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$2.invoke(VaultItemListingViewModel.kt:192)
	at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(Emitters.kt:50)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$$inlined$map$1$2.emit(Emitters.kt:50)
	at com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingViewModel$observeVaultData$$inlined$map$1$2$1.invokeSuspend(Unknown Source:15)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:35)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:101)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at android.os.Handler.handleCallback(Handler.java:958)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:230)
	at android.os.Looper.loop(Looper.java:319)
	at android.app.ActivityThread.main(ActivityThread.java:9063)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: kotlinx.serialization.MissingFieldException: Field 'transports' is required for type with serial name 'com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor', but it was missing
	at kotlinx.serialization.internal.PluginExceptionsKt.throwMissingFieldException(PluginExceptions.kt:20)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor.<init>(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at com.x8bit.bitwarden.data.autofill.fido2.model.PublicKeyCredentialDescriptor$$serializer.deserialize(PublicKeyCredentialDescriptor.kt:9)
	at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
	... 59 more

[2025-02-12 12:16:23] PASSKEY	A  vaultLoadedReceive called with GetCredentialsRequest but assertionOptions or relyingPartyId are null.

@SaintPatrck
Copy link
Contributor Author

@BJReplay give this build a shot when you can: https://github.com/bitwarden/android/actions/runs/13276476757

@BJReplay
Copy link

@BJReplay give this build a shot when you can:

Will do, probably a couple of hours from now. Will report back.

@BJReplay
Copy link

@SaintPatrck tried that build (dev) and it logged in! You have a fix.

[2025-02-12 16:58:17] PASSKEY	D  processGetCredentialRequest received from package au.com.bank86400 with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}]
[2025-02-12 16:58:19] PASSKEY	D  processGetCredentialRequest received from package au.com.bank86400 with bundle: Bundle[{androidx.credentials.BUNDLE_KEY_REQUEST_JSON={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH=null, androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE=100, android.service.credentials.BeginGetCredentialOption.BUNDLE_ID_KEY=<redacted>, androidx.credentials.BUNDLE_KEY_SUBTYPE=androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION, androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED=true}]
[2025-02-12 16:58:23] PASSKEY	D  getFido2AssertionRequestOrNull returned request: Fido2CredentialAssertionRequest(userId=<redacted>, cipherId=<redacted>, credentialId=<redacted>, requestJson={"challenge":"<redacted>","timeout":120000,"rpId":"www.ubank.com.au","allowCredentials":[{"type":"public-key","id":"g_LB7hNTzGX2E-i9VAh_PQ"},{"type":"public-key","id":"Ufu8PiSAb1gSDZ1WD1RDYw"},{"type":"public-key","id":"gdRWDim7QZquVJfq-mE4vQ"}],"userVerification":"required"}, clientDataHash=null, packageName=au.com.bank86400, signingInfo=android.content.pm.SigningInfo@4ca5184, origin=null, isUserVerified=false)

Send it!

@SaintPatrck SaintPatrck removed the hold do not merge yet label Feb 12, 2025
Copy link
Collaborator

@dseverns-livefront dseverns-livefront left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SaintPatrck
Copy link
Contributor Author

image

@SaintPatrck SaintPatrck merged commit 0820061 into main Feb 12, 2025
9 checks passed
@SaintPatrck SaintPatrck deleted the PM-11886/update-origin-for-unprivileged-apps branch February 12, 2025 22:52
onFailure = { Fido2RegisterCredentialResult.Error },
onFailure = {
Fido2RegisterCredentialResult.Error(
R.string.passkey_registration_failed_due_to_an_internal_error.asText(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not have a Text inside the data package, that is a ui only class

@@ -13,5 +15,5 @@ sealed class Fido2CredentialAssertionResult {
/**
* Indicates there was an error and the assertion was not successful.
*/
data object Error : Fido2CredentialAssertionResult()
data class Error(val message: Text) : Fido2CredentialAssertionResult()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't have this in the data package

@SaintPatrck SaintPatrck mentioned this pull request Feb 18, 2025
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Passkey support with UBank
5 participants