Explore how WebAuthn transports work in browser APIs, iOS AuthenticationServices, and Android Credential Manager for cross-device passkey authentication.

Vincent
Created: October 30, 2025
Updated: November 12, 2025

60-page Enterprise Passkey Whitepaper:
Learn how leaders get +80% passkey adoption. Trusted by Rakuten, Klarna & Oracle
| Platform | Platform Authenticators | Security Keys |
|---|---|---|
| Web Browsers | Windows Hello: ["internal"]Google Password Manager: ["internal", "hybrid"]iCloud Keychain: ["internal", "hybrid"] | ["usb", "nfc"] |
| Android Native | ["internal", "hybrid"] | ["usb", "nfc"] |
| iOS Native | ⚠️ Empty [] (iCloud Keychain) | ["usb", "nfc"] |
Note: Per WebAuthn specification, empty transports means all transports are supported.
When implementing passkeys across platforms, developers face an important decision:
The answer lies in understanding WebAuthn transports-a technical detail that determines how authenticators communicate with relying parties. While transports seem straightforward in theory, their implementation varies significantly across web browsers, native iOS, and native Android applications, particularly for internal and hybrid transport handling.
This article examines how WebAuthn transports work across different platforms and presents two distinct approaches to handling internal and hybrid transports-each with its own trade-offs.
This article covers:
WebAuthn transports define the communication methods between authenticators and client devices. The WebAuthn Level 3 specification defines six transport types:
usb: Used by hardware security keys that
connect via USB ports, such as YubiKeys or other
FIDO2 security tokens.
nfc: Enables communication with authenticators through
Near Field Communication, allowing users to tap their security keys or NFC-enabled
devices.
ble: Facilitates authentication via Bluetooth Low Energy,
enabling wireless communication with external authenticators.
smart-card: Used for smart card readers, allowing
authentication via smart cards.
hybrid: Enables cross-device authentication, typically where a user scans a
QR code to authenticate across devices-such as using
a phone to authenticate on a desktop browser, or vice versa. This transport can trigger
QR code prompts on both desktop and mobile devices,
which may not always be desirable depending on the context. Note: hybrid was added in
WebAuthn Level 3.
internal: The authenticator is embedded within the device
itself-like iCloud Keychain (verified via Face ID or Touch
ID) on iPhones, Windows Hello on PCs, or
Google Password Manager on
Android devices. These are platform
authenticators.
When a passkey is created, the authenticator signals which
transports it supports. This information gets sent to the
relying party (your backend), which should persist it alongside
the credential. During authentication, the relying party sends
these transports back to the client in the allowCredentials list, helping the browser or
platform determine which authentication methods to offer the user.
Transport handling differs significantly across platforms, creating the compatibility challenges developers face.
Browsers receive transport information from authenticators and honor it during authentication flows. When you create a passkey in Chrome, Safari, or Edge, the browser's credential manager provides transport data that varies based on the underlying authenticator:
Platform authenticators: Windows Hello provides
["internal"] only, reflecting its device-bound nature. However, when Chrome uses
Google Password Manager as the authenticator,
it provides ["internal", "hybrid"] because
Google Password Manager supports cross-device
authentication via Android Phones.
Hardware security keys: Provide specific transports like ["usb", "nfc"] based on
their actual capabilities.
Cloud-synced credential managers: iCloud Keychain in
Safari and Google Password Manager in Chrome typically provide ["internal", "hybrid"] to
support both local and cross-device authentication flows.
This information flows reliably in web contexts, though the specific transports depend on which authenticator the browser selects for credential storage.
Documentation: W3C WebAuthn Specification
Android's Credential Manager API behaves similarly to web browsers. When creating passkeys in native Android apps, the Credential Manager provides transport information that mirrors web behavior-platform authenticators report their capabilities accurately, and the system handles transport data consistently. Android developers can rely on this information without special handling.
Documentation: Android Credential Manager
iOS presents a more complex situation. Apple's AuthenticationServices framework handles transports differently depending on the authenticator type:
Platform authenticators (iCloud Keychain, verified via Face ID or Touch ID): Often return empty transport arrays during passkey creation. This doesn't mean the passkey lacks transport capabilities-it simply means iOS doesn't report them explicitly. According to the WebAuthn standard, leaving out transports means any transport is acceptable, so hybrid authentication will still work.
Security keys: Do provide transport information (e.g., ["usb"], ["nfc"]) when used
with iOS devices, following the expected pattern.
Documentation: Apple AuthenticationServices
Real-world production data from web and native applications reveals the following transport patterns, ordered by frequency. Note that these distributions are influenced by implementation specifics and client demographics (mobile vs desktop usage, availability of native apps), but they provide valuable insight into typical transport usage:
| Transport Pattern | Frequency | Source |
|---|---|---|
["internal", "hybrid"] | Very common | Cloud-synced credential managers (iCloud Keychain, Google Password Manager) on web and native |
["hybrid", "internal"] | Very common | Same as above, order variation |
[] (empty array) | Very common | iOS native platform authenticators |
["internal"] | Common | Windows Hello, device-bound authenticators |
["internal", "cable"] | Rare | Legacy notation for hybrid (cable = old terminology) |
["nfc", "usb"] | Very rare | Hardware security keys |
["usb"] | Very rare | USB-only security keys |
["hybrid"] | Very rare | Hybrid-only configurations |
Key Insights:
Platform authenticators dominate: The vast majority of passkeys use internal
transport, often combined with hybrid for cross-device authentication support. This
reflects the consumer focus on platform authenticators
(iCloud Keychain,
Google Password Manager).
Empty arrays are common: iOS native applications frequently return empty transport arrays for platform authenticators, representing a significant portion of production credentials. As discussed in section 2.2.3, these should be interpreted as "any transport acceptable" per specification.
Security keys are rare:
Hardware security keys (usb, nfc) represent
a tiny fraction of production passkeys, indicating their primary use in enterprise or
high-security scenarios rather than consumer applications.
Order variations exist: The order of transports in arrays (["internal", "hybrid"] vs
["hybrid", "internal"]) varies by platform and authenticator
implementation but carries no functional difference - both indicate support for the same
transport methods.
Legacy terminology: The cable transport identifier appears occasionally in older
implementations and is synonymous with hybrid (caBLE = cloud-assisted Bluetooth Low
Energy, the original name for the hybrid transport).
This distribution reinforces the importance of handling internal and hybrid transports
correctly, as they account for the overwhelming majority of real-world passkey
implementations.
The same authenticator often reports different transport patterns based on platform, version, and implementation context. This variation is normal and expected:
iCloud Keychain exhibits three patterns:
["internal", "hybrid"] - Most common, typically from web browsers[] (empty array) - Very common, from iOS native apps["hybrid", "internal"] - Less common, order variation["internal"] or ["hybrid"] alone - Rare edge casesGoogle Password Manager shows the most variation:
["hybrid", "internal"] - Most common pattern["internal", "hybrid"] - Common alternative ordering["internal", "cable"] - Legacy implementations (cable = old term for hybrid)[] (empty array) - From certain native contextsWindows Hello is most consistent:
["internal"] - Dominant pattern (device-bound by design)‚Password managers like 1Password, Bitwarden, Dashlane, and LastPass all show similar variation patterns:
["internal", "hybrid"] and ["hybrid", "internal"] orderings[] from native app contexts["internal"]Samsung Pass (Android ecosystem) primarily uses:
["hybrid", "internal"] and ["internal", "hybrid"] - Both orderings commonPlatform differences: The same authenticator behaves differently on web vs native, iOS vs Android, or Windows vs macOS.
Version evolution: Transport reporting has evolved over time. Older versions may use
cable instead of hybrid, or report different combinations.
Implementation choices: Some authenticators prioritize internal first, others
hybrid. The order has no functional impact but varies by implementation.
Context sensitivity: Native apps, especially on iOS, often receive empty arrays even from authenticators that report full transports in web contexts.
Key Takeaway: Don't assume transport arrays will be consistent for a given authenticator. Design your implementation to handle all variations gracefully, focusing on the presence of specific transports rather than exact array matching.
Developers face a choice: follow the specification strictly, or optimize internal and hybrid transports for user experience. Each approach has merits and drawbacks.
This approach aligns with the WebAuthn specification: use transports exactly as provided by the authenticator during credential registration, and send them back unchanged during authentication.
Implementation: When a passkey is created, persist the transports array from the
authenticator response. During authentication, include these exact transports in the
allowCredentials list:
{ "allowCredentials": [ { "id": "credential-id-base64", "type": "public-key", "transports": ["internal", "hybrid"] } ] }
Advantages:
Disadvantages:
Best for: Applications prioritizing standards compliance, enterprise environments with diverse authenticator types.
This approach prioritizes user experience by selectively modifying internal and hybrid transports based on specific optimization goals. Rather than a blanket rule, consider these common optimization scenarios:
Problem: iOS platform authenticators return empty transport arrays. When left empty or filled by backends, users might see security key prompts (USB, NFC) alongside platform options, creating confusion in consumer applications.
Solution: Explicitly set transports to ["hybrid", "internal"] for iOS platform
authenticators. This ensures only platform authentication and cross-device flows are
offered, hiding security key options.
// When persisting iOS platform authenticator credentials if (platform === "iOS" && authenticatorAttachment === "platform") { transports = ["hybrid", "internal"]; }
Result: Clean authentication UI without security key prompts for iOS-created passkeys.
Problem: When authenticating on mobile devices, showing QR codes for cross-device authentication creates poor UX-users are already on a mobile device with their passkeys available.
Solution: Remove hybrid transport when the user is authenticating from a mobile
device, leaving only ["internal"].
// When building allowCredentials for authentication const transports = isMobileDevice ? credentials.transports.filter((t) => t !== "hybrid") : credentials.transports;
Result: Mobile users see only direct authentication options without unnecessary QR code prompts.
⚠️ Caution: Transport manipulation doesn't always produce consistent results across platforms. Extensive testing shows that browser and OS combinations handle transports differently:
hybrid is excluded from transportshybrid is includedRisk of deadends: Overly restrictive transport filtering can create authentication
deadends where users cannot log in at all. For example, removing hybrid might prevent
legitimate cross-device authentication scenarios where a user needs to authenticate from a
borrowed device. Always provide fallback authentication methods and test thoroughly across
your target platforms before deploying transport optimizations.
These are optimization hints: WebAuthn provides other mechanisms to optimize authentication UX beyond transport manipulation-such as hints.
Transport behavior is unpredictable: Cross-device authentication (CDA) via hybrid
transport exhibits inconsistent behavior across browser and OS combinations.
Real-world testing
demonstrates that transport values don't guarantee specific UI behavior-platforms
interpret and handle transports differently, leading to unexpected results.
Platform-specific complexity: When explicitly controlling transports, you must account for platform differences:
["internal"] only; adding hybrid triggers unwanted QR
codeshybrid
presence in transports arrayEnd-to-end understanding required: Explicitly controlling transports means taking responsibility for the entire flow. You must understand how each transport combination behaves across all your target platforms and test thoroughly. Transport manipulation can create authentication deadends where no valid authentication path exists for users.
Advantages:
Disadvantages:
Best for: Consumer applications with specific UX requirements, teams with resources to maintain platform-specific logic, scenarios prioritizing streamlined authentication flows over strict spec compliance.
WebAuthn transport handling doesn't exist in isolation-it's one piece of your overall passkey implementation strategy. Two common approaches emerge in production deployments, each with different implications for internal and hybrid transport usage.
This approach prioritizes flexibility and standards compliance, allowing users to authenticate with any compatible authenticator.
Implementation Characteristics:
[], allowing any credential to matchusb, nfc, ble)Transport Implications:
With empty allowCredentials, transports become less critical during authentication-the
platform shows all available options. However, this means users may see security key
prompts, QR codes, and platform options simultaneously, which can create decision
paralysis in consumer applications.
Best for: Enterprise environments, applications with diverse user bases requiring security key support, scenarios prioritizing maximum authentication flexibility.
This approach optimizes for consumer UX by restricting passkey creation to platform authenticators and using identifier-first flows.
Implementation Characteristics:
authenticatorAttachment: "platform" to focus on immediately available
authenticatorsauthenticatorAttachment restriction, allowing power users to select any authenticator
including security keyspreferImmediatelyAvailableCredentials for silent,
instant authentication without prompts for security keys or QR codespreferImmediatelyAvailableCredentials (users typically authenticate on the
device where their passkeys reside)internal and hybrid transportsTransport Implications:
Since allowCredentials contains specific credentials with their transports, transport
handling becomes crucial for optimizing authentication experiences.
Security Key Reality: Security keys represent an extremely small fraction of passkey usage in large-scale consumer deployments-primarily power users or users with specific security requirements. The consumer-tailored approach acknowledges this reality by supporting security keys without optimizing primary flows around them.
Two-Tier Creation Strategy: Implementations can balance security key compatibility with optimized consumer UX through dual creation paths:
authenticatorAttachment: "platform", guiding users toward immediately available
passkeys with high success ratesauthenticatorAttachment, allowing
power users to select security keys, third-party password managers, or any available
authenticatorThis pattern appears in major implementations: security keys are supported and functional via settings, but user-facing nudges optimize for the dominant use case-platform authenticators that provide instant, silent authentication.
Best for: Consumer applications, native mobile apps, scenarios prioritizing streamlined UX over authenticator flexibility, platforms where identifier-first flows already exist.
| Characteristic | Standard Conformity | Consumer-Tailored |
|---|---|---|
| allowCredentials | Empty array | User-specific credentials |
| Authenticator types | All (platform, security keys, CDA) | Platform + CDA (primary), security keys (via settings) |
| Native app API | Standard WebAuthn | preferImmediatelyAvailableCredentials |
| Security keys | Supported in all flows | Supported via settings |
| Transport relevance | Low (empty allow list) | High (specific credentials) |
| Mobile QR codes | May appear | Can be optimized away |
| User experience | More options, more complexity | Streamlined primary flows, power user options available |
| Implementation complexity | Lower | Higher (context-aware transport logic) |
| Consumer friction | Higher (multiple auth choices) | Lower (optimized for dominant use cases) |
For platforms that already leak account existence or use identifier-first flows (user enters email before seeing login options), the consumer-tailored approach aligns naturally. Once the user has provided their identifier:
allowCredentials with specific credentials and their transportsIn these scenarios, transports can become optimization tool rather than a security concern. You can tailor authentication options based on device context (mobile vs. desktop) and credential capabilities.
Recommendation: For platforms that already use identifier-first flows or where
account enumeration
isn't a concern, the consumer-tailored approach with explicit transport handling provides
superior UX, especially in native mobile applications where
preferImmediatelyAvailableCredentials enables seamless
biometric authentication.
Regardless of which approach you choose for handling internal and hybrid transports, follow these practices to minimize issues:
Persist Transports During Registration: Always store the transports array from the
authenticator response alongside the credential ID
and public key. This data is essential for authentication flows.
Handle Empty Arrays Gracefully: When receiving an empty transport array from iOS platform authenticators:
["internal", "hybrid"] to control which
authentication options are shownWeb vs Native Transport Strategies: Differentiate transport handling based on context:
preferImmediatelyAvailableCredentials for silent
authentication; transports sent as storedHandle Security Key Authentication: When users have security keys registered:
Test Across All Target Platforms: Create a testing matrix covering all combinations:
preferImmediatelyAvailableCredentialsauthenticatorAttachmentUnderstand Empty Array vs. Missing Property: Both an empty transports array [] and a
missing transports property are typically treated as "any transport is acceptable"
according to the specification. However, implementation details vary across platforms.
Monitor Platform Changes: WebAuthn implementations evolve. Apple, Google, and Microsoft regularly update their authenticator behaviors. Stay informed about changes that might affect transport handling.
WebAuthn transports-especially internal and hybrid transports-are technical details with significant practical impact on cross-device authentication. Your transport handling strategy should align with your broader passkey implementation approach and target platforms.
Transport Decisions Live Within Broader Strategy: How you handle transports depends on whether you're building for maximum flexibility (empty allowCredentials) or consumer UX (identifier-first with specific credentials). The latter makes transports critical for optimization.
Platform Differences Require Handling: Web and Android provide reliable transport
information, while iOS platform authenticators return empty arrays. Windows Hello sends
only ["internal"]. Understanding these differences is essential for production
deployments.
Two Valid Transport Approaches: Spec-compliant (trust authenticator transports) works well for enterprise and maximum flexibility scenarios. Explicit control (optimize transports) suits consumer applications with identifier-first flows and native mobile apps.
Identifier-First Enables Transport Optimization: When users provide their identifier first, transport handling becomes a powerful UX tool. You can prevent unwanted QR codes on mobile, hide security key options, and streamline authentication-without additional account enumeration concerns.
For Enterprise / Maximum Flexibility:
allowCredentials to support all authenticator typesFor Consumer Applications / Native Apps:
authenticatorAttachment: "platform"
for high-success immediate authenticationauthenticatorAttachment for power users
needing security keysallowCredentials with specific credentials and optimized transportspreferImmediatelyAvailableCredentials for silent authentication["hybrid", "internal"]hybrid on mobile devices to prevent QR codes where appropriateFor Platforms with Identifier-First Flows Already:
Start spec-compliant, then optimize based on your strategy:
The WebAuthn landscape continues evolving. Platform vendors regularly update their implementations, and specifications like WebAuthn Level 3 introduce new capabilities. Building flexible systems that align transport handling with your broader authentication strategy ensures your passkey implementation remains robust and provides excellent user experiences as the ecosystem matures.
Related Articles
Table of Contents