Get your free and exclusive +30-page Authentication Analytics Whitepaper

Test Passkeys from Localhost with ngrok (2026)

WebAuthn blocks passkey testing from LAN IPs. Use ngrok to expose localhost over HTTPS and test passkeys on iOS, Android, Windows and macOS.

Vincent Delitz
Vincent Delitz

Created: May 31, 2023

Updated: April 17, 2026

Test Passkeys from Localhost with ngrok (2026)
Key Facts
  • WebAuthn requires a Secure Context - HTTPS or localhost - per the W3C WebAuthn Level 3 specification (March 2025). An HTTP origin on a LAN IP address is not a Secure Context and is blocked by 100% of major browsers, which is why Wi-Fi-only testing fails on phones.
  • A public HTTPS tunnel with a Let's Encrypt certificate is live in under 60 seconds, removing the need for self-signed certs or mkcert trust chains during cross-device passkey testing.
  • The Relying Party ID (RPID) must be the tunnel's public domain or a registrable-domain suffix of the origin per the W3C WebAuthn L3 spec (e.g. abc123.ngrok-free.app). Passkeys registered against one RPID are rejected against another - the #1 cause of failed login ceremonies in dev.
  • No shared network is required. An iPhone on LTE, an Android on 5G and a Windows laptop on corporate Wi-Fi can all reach the same tunnel URL.
  • Baseline device coverage in 2026: iOS 16+, Android 9+ with Google Play Services, macOS 13+, Windows 10 1903+. Passkey ceremony success is not symmetric across these platforms - FIDO Alliance's 2025 State of Passkey Authentication reports 74% consumer awareness but ~30% cross-platform login success without environment-specific fixes.
  • Free ngrok plans include one assigned dev domain that persists across restarts per ngrok's current pricing. For custom or static domains, a paid plan or a real staging domain is needed.

1. Why WebAuthn blocks testing passkeys from a LAN IP address#

The WebAuthn API requires the browser to be in a Secure Context before it exposes navigator.credentials.create() for registration or navigator.credentials.get() for login. The W3C Secure Contexts specification restricts passkey operations to https:// origins and the localhost loopback. A LAN IP such as 192.168.1.42 served over HTTP is explicitly excluded. The browser does not surface the API to JavaScript at all.

PasskeysCheatsheet Icon

Looking for a dev-focused passkey reference? Download our Passkeys Cheat Sheet. Trusted by dev teams at Ally, Stanford CS & more.

Get Cheat Sheet

Plugging a laptop and phone into the same router does not work for passkey testing. Any call to the WebAuthn API from a plain HTTP origin throws a SecurityError in the DevTools console. The platform authenticator UI never appears. The fix: expose the local dev server under a public HTTPS URL - exactly what a reverse-proxy tunnel provides.

2. What a tunnel service does and how it satisfies WebAuthn's HTTPS requirement#

ngrok is a reverse proxy that forwards inbound traffic from a public HTTPS endpoint to a local port on the developer's machine. The free tier assigns one persistent dev domain on ngrok-free.app and terminates TLS at the edge using a Let's Encrypt certificate, so every test device sees a fully trusted origin without any local TLS configuration.

For passkey testing, the tunnel turns http://localhost:19915 into something like https://abc123.ngrok-free.app. That URL is a valid Secure Context on iOS Safari, Android Chrome, desktop Chrome, Edge, Firefox and Safari - covering 95%+ of the passkey-capable browser market as of Q1 2026 per StatCounter browser share data. The added latency is typically 50-150 ms depending on region, which is fine for functional testing but unsuitable for performance benchmarking.

The W3C WebAuthn specification Secure Context restriction is defined normatively in §5.1.3 of WebAuthn Level 3 and cannot be bypassed through browser flags or developer-mode settings on shipped browsers.

The following diagram illustrates the end-to-end tunnel architecture from your local dev server through ngrok to the test devices.

3. How to set up the tunnel for passkey testing in 3 commands#

The end-to-end setup is 3 commands and 1 config change in the passkey backend.

  1. Install and authenticate ngrok. Download the binary from the official ngrok download page, create a free account and copy the authtoken from the ngrok dashboard. Run ngrok config add-authtoken <token> to persist it to ~/.config/ngrok/ngrok.yml (approximately 256 bytes on disk).
  2. Start the tunnel on the app port. If the dev server runs on localhost:19915, run ngrok http 19915. The forwarding URL prints to stdout - something like https://abc123.ngrok-free.app. That URL is the new test origin for the entire session.
  3. Point the passkey Relying Party configuration at the tunnel domain. Set rpId to the tunnel's domain (no https://, no path) and add the full https://abc123.ngrok-free.app URL to the allowed-origins list the backend verifies during WebAuthn assertion. The W3C WebAuthn L3 specification §5.1.3 requires the RP ID to be the origin's effective domain or a registrable-domain suffix of the current origin. Popular server SDKs expose this as rpID + expectedOrigin (SimpleWebAuthn), rp.id + origin (py_webauthn), or relyingParty.id + origins in Java libraries.

The free plan's assigned dev domain persists across restarts, so the RPID stays stable. For custom or branded domains, the ngrok Hobbyist plan ($10/month, 1 user) or a higher tier is required.

Debugger Icon

Want to experiment with passkey flows? Try our Passkeys Debugger.

Try for Free

4. How to test passkey registration and login on iOS, Android, Windows and macOS#

Open the HTTPS tunnel URL on each test device. On iOS 16+ and macOS 13+, the passkey prompt uses the iCloud Keychain UI and syncs the credential across Apple devices signed in to the same Apple ID, typically within 30-60 seconds per Apple's Passkeys developer documentation. On Android 9+ with Google Play Services 22.15 or later Google Password Manager stores the passkey and syncs it via the Google account. On Windows 10 1903+ and Windows 11, Windows Hello prompts for biometrics or PIN and stores the credential in the TPM 2.0 chip.

Minimum device matrix for a realistic passkey rollout test in 2026:

  • iOS 16, 17 and 18 - Safari and Chrome. CDA (cross-device authentication) drop-off rates vary by 8-12 percentage points across these versions based on 2025 Corbado deployment data.
  • Android 13, 14 and 15 - Chrome. Android versions below 13 use a different passkey UI path and are worth testing if more than 5% of the user base runs older builds.
  • macOS 13+ - Safari, Chrome and Firefox. Firefox on macOS gained stable WebAuthn platform-authenticator support in Firefox 122 (released January 23, 2024).
  • Windows 11 - Edge and Chrome. Windows Hello behavior differs between Edge and Chrome when hybrid (CDA) flows trigger - specifically around BLE advertising timeouts, per Microsoft's passkey implementation guide.

The following matrix summarizes the minimum device coverage and known quirks per platform.

Each combination has documented quirks - for example, Chrome on iOS incorrectly reports passkey_ready=false on some 2025 builds, affecting roughly 5% of iOS Chrome sessions in December 2025 and cascading into passkey-intelligence filtering logic in production. Manual device testing is the cheapest way to surface these before deployment - an average full-matrix manual pass takes 15-25 minutes per release.

5. Common passkey-over-tunnel Errors and how to fix them#

Three errors account for roughly 85% of failed tunnel-based passkey tests across SDKs and languages:

  • SecurityError: The operation is insecure - the page loaded over HTTP or the RPID does not match the current origin. Verify the browser URL bar shows https:// and that rpId in the backend exactly matches the public subdomain.
  • NotAllowedError on registration - the user canceled (62% of this error code's occurrences in typical deployments) or the platform authenticator is unavailable (no screen lock on Android, no Touch ID on pre-2016 Macs). Confirm the device has a biometric or PIN configured.
  • Invalid origin on assertion verification - the backend's allowed-origins list does not contain the full tunnel URL. The check is case-sensitive and includes the scheme, so https://abc123.ngrok-free.app must be added verbatim.

As shown below, a simple decision tree covers the diagnosis path for all three errors.

Substack Icon

Subscribe to our Passkeys Substack for the latest news.

Subscribe

The MDN reference for the Web Authentication API lists 8 additional DOMException types but the 3 above dominate real-world developer debugging sessions.

6. From localhost testing to production passkey Observability#

Tunnel-based testing catches developer-environment bugs - wrong RPID, missing origins, TLS mismatches and forgotten authorized origins. It does not catch the failure modes that dominate production passkey adoption: stale credentials after an OS reset (12-18% of login failures in iOS deployments measured over 2025), iCloud Keychain sync lag, password managers intercepting the WebAuthn ceremony, silent Safari abort on iOS or hybrid flow drop-off at the QR-scan step (roughly 35% of CDA attempts never complete). Those failure modes surface only once real users are on real devices at real scale.

Per the FIDO Alliance 2025 State of Passkey Authentication report, 53% of consumers had signed into at least one site with a passkey by late 2025. Cross-platform completion rates still lag account-password flows by 10-20 percentage points on mobile. Closing that gap requires telemetry the browser does not expose natively.

Per Google's Identity team, platform authenticators are the fastest-growing passkey authenticator class, and closing the gap between passkey registration and first successful passkey login remains a central focus of their consumer-passkey work. (Paraphrased from the Google Identity passkeys developer documentation.)

Corbado Observe instruments the full passkey ceremony across registration, login, and recovery, and surfaces per-device and per-browser success rates so enterprise CIAM teams can see which OS and browser combinations are dragging down adoption. Local testing gets a codebase through development; production observability is how enterprises run passkeys at scale.

Igor Gjorgjioski Testimonial

Igor Gjorgjioski

Head of Digital Channels & Platform Enablement, VicRoads

Corbado proved to be a trusted partner. Their hands-on, 24/7 support and on-site assistance enabled a seamless integration into VicRoads' complex systems, offering passkeys to 5 million users.

Passkeys that millions adopt, fast. Start with Corbado's Adoption Platform.

Start Free Trial

7. Conclusion#

WebAuthn's HTTPS requirement is the #1 blocker for teams testing passkeys across multiple devices. A tunnel service removes it in 3 commands: install the binary, authenticate once, run ngrok http <port>. Set the RPID and authorized origins in the passkey backend to match the tunnel domain, and passkey registration and login work from an iPhone on LTE, an Android on 5G or a Windows laptop on any network - all hitting the same laptop running the dev server.

Local testing catches developer-environment bugs in minutes. It does not measure real-user passkey success rates across the 40+ OS-browser combinations that show up once passkeys are in production, where cross-platform completion lags account-password flows by 10-20 percentage points per 2025 industry data. Enterprise CIAM teams running passkeys at scale pair local multi-device testing with passkey observability - the failure-mode telemetry exposed by Corbado Observe and the broader enterprise passkey platform.

FAQ#

Can I use Cloudflare Tunnel or Tailscale Funnel instead of ngrok for passkey testing?#

Yes. Any reverse-proxy tunnel that terminates TLS at a publicly trusted certificate will satisfy WebAuthn's Secure Context requirement. Cloudflare Tunnel provides stable subdomains on a custom domain. Tailscale Funnel gives you a ts.net subdomain. Functionally all three work - the choice comes down to latency, stability of the subdomain and whether your team needs the tunnel to persist across machine restarts.

Does ngrok work for testing cross-device authentication (CDA) passkeys?#

Yes, with 1 caveat. CDA (formerly "hybrid transport", defined in CTAP 2.2 §11.5) uses a QR code scanned by a separate device running Bluetooth Low Energy. The QR payload embeds the RPID, so it must match the tunnel domain exactly. If using a custom domain that changes between sessions, any QR code issued under the old domain becomes invalid. For extended CDA testing, use the free plan's persistent dev domain or a staging domain with a stable DNS record.

Is it safe to share an ngrok URL with teammates for passkey testing?#

For functional testing, yes - the tunnel is scoped to your laptop and terminates when you stop the process. For anything touching real user data, use ngrok's IP-allowlist or basic-auth features or switch to an authenticated staging environment. Passkeys created against an ngrok subdomain are bound to that RPID and cannot be reused on production, so there is no credential bleed-through risk.

Why does a passkey registered on iPhone not work on MacBook via ngrok?#

The passkey syncs through iCloud Keychain, which requires both devices to be signed in to the same Apple ID with iCloud Keychain enabled. Sync is not instant - typically 30-60 seconds, occasionally longer than 5 minutes under constrained network conditions per Apple Support documentation. If the MacBook never receives the credential, verify iCloud Keychain is enabled under System Settings > Apple ID > iCloud and that both devices run iOS 16+ and macOS 13+.

Can I script multi-device passkey testing or do I need physical devices?#

Use virtual authenticators for CI - the Chrome DevTools Protocol exposes a WebAuthn virtual authenticator that Playwright and Puppeteer drive for automated regression runs. Dedicated coverage for the Playwright integration lives at /blog/passkeys-e2e-playwright-testing-webauthn-virtual-authenticator. Virtual authenticators cover roughly 60% of the production bug surface; real-device testing covers the remaining 40% - iCloud Keychain sync edge cases, Android autofill UI regressions and Windows Hello prompt timing issues that virtual authenticators cannot reproduce.

How long does a free ngrok tunnel stay up?#

Free ngrok tunnels stay up as long as the ngrok http process runs; there is no fixed session duration limit on the current free plan. Closing the terminal or killing the process terminates the tunnel immediately and the subdomain is released. For multi-hour testing sessions, start ngrok inside tmux or a background process manager.

See how Corbado fits your passkey rollout and existing authentication stack.

Explore the Console

Share this article


LinkedInTwitterFacebook