Skip to content

fix(ios): preserve passkey bytes and own request completion safely - #114

Open
OskarEichler wants to merge 1 commit into
f-23:stablefrom
OskarEichler:codex/ios-binary-and-request-ownership
Open

fix(ios): preserve passkey bytes and own request completion safely#114
OskarEichler wants to merge 1 commit into
f-23:stablefrom
OskarEichler:codex/ios-binary-and-request-ownership

Conversation

@OskarEichler

Copy link
Copy Markdown

Fixes and behavior changes

This fixes several related iOS bridge correctness and lifetime problems:

  • Preserve large-blob bytes exactly, using numeric byte indices rather than lexicographic ordering and machine-sized Int/UInt memory. A 12-byte write previously became 96 bytes on a 64-bit platform; reading returned one machine-sized integer and discarded the remainder.
  • Return large-blob records with zero-based byte indices. This is an observable output correction. Previously stored blobs may contain the old corrupted encoding; inspect/rewrite them from original data rather than assuming automatic migration.
  • Normalize binary extension inputs before iOS JSON serialization, so ArrayBuffer data is not lost. Share safe decoding for base64url strings, byte arrays and legacy numeric-key records; invalid indices/bytes reject rather than trap.
  • Decode PRF credential keys from base64url (not UTF-8), accept both record and legacy array forms, and reject per-credential PRF when allowCredentials is absent as well as empty. Remove logging of PRF input values.
  • Decode and cache valid descriptor IDs once, reject missing/invalid IDs and missing RP IDs through decoding errors, and preserve all supported transports rather than only the first.
  • Stop after missing attestation/signature errors instead of force-unwrapping nil.
  • Break the module/delegate retain cycle; clear handlers after settlement; make delegate completion one-shot. Reject an overlapping create/get with RequestFailed instead of overwriting the first promise. Run bridge methods on the main queue, aligned with authorization callbacks.

Public method signatures are unchanged. Invalid inputs, overlapping requests, large-blob output and PRF credential matching intentionally receive corrected behavior. A passkey creation/get ceremony is not started by any verification harness.

Verification

  • Baseline and combined fixes: all 30 existing JS tests pass; TypeScript, full ESLint, CommonJS/ESM/declaration builds and diff checks pass. No test files changed.
  • 2,580 JS serialization cases across both platforms and five binary representations; 387 Swift binary round trips; nine malformed input cases; multi-transport and both PRF credential-map forms.
  • Swift harnesses run actual decoder/method bodies with controlled inputs: retained cycle true -> false, duplicate completions 2 -> 1, overlap no longer replaces the original handler, handlers clear on success/error. The harness is not a live native authentication session.
  • Consumer verification uses a 3.6.1 backport excluding unrelated changes on stable: both Android Debug flavors, both iOS simulator Debug schemes, and all four release-mode Metro bundles pass on RN 0.87.1. Installed distributables/native sources match the verified build. App immutable install and lint pass.
  • Existing Swift unreachable-default and builder-bob tsc-discovery warnings remain. No real passkey registration, login, deletion, credential Signal API call, or physical authenticator test was performed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant