Urgent.News

What's breaking now, across thousands of outlets.

Tech

Testing Passkeys Through a Tunnel: RP ID, Origins, and Why Credentials Don’t Follow You From localhost

You build a passkey flow on http://localhost:3000 . Registration works, login works, and you feel done. Then you open a tunnel so a real phone can try it, and the login screen offers no passkeys at all. Nothing is broken in the usual sense. The tunnel is up, the certificate is valid, the browser is happy. Your credentials simply live somewhere else. Passkeys are bound to a domain, not to your app…

When you build a passkey flow on a local server like http://localhost:3000, the registration and login processes work smoothly. However, when you try to test the login with a real phone over a tunnel, the passkey login screen shows no passkeys at all. This isn't due to any error in the system; instead, passkeys are tied to a specific domain, not your app or laptop.

When testing through a tunnel, the tunnel's hostname becomes part of the credential, causing the credentials to be separate from those registered on the local domain.

A passkey is associated with a single Relying Party ID (RP ID), which is essentially a domain name. The RP ID must match the page's hostname or be a registrable parent domain of it. It cannot be a public suffix like "com". Your server verifies both the RP ID and the full origin (scheme, host, and port) separately. Therefore, a random tunnel URL, which changes both the RP ID and the origin each time it's used, will orphan any passkeys previously registered.

To resolve this issue, using a stable, named tunnel subdomain ensures a consistent RP ID. This way, passkeys registered on the local domain can be authenticated on the tunnel-hosted page. An RP ID is simply the effective domain of the page, without any additional scheme, port, or path. For example, for a page on www.example.com, a valid RP ID would be "www.example.com" or "example.com". However, public suffixes such as "com" are not accepted.

It's crucial to remember that localhost credentials and tunnel-hostname credentials are distinct environments. Credentials registered for localhost won't authenticate under a tunnel hostname. Hence, it's essential to treat these environments as separate when testing. While the authenticator (like iCloud Keychain, Google Password Manager, or Windows Hello) only offers credentials matching the RP ID, your database might still hold public keys attached to an RP ID you no longer serve.

Therefore, two checks are needed: one for the RP ID and another for the origin. These checks ensure that passkeys work seamlessly across different environments.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Embiody 0.9 Preview Arrives: The Browser for AI Agents That Don't Slow Down in the Background

Browsers are designed for people; an AI agent can use them, but they don't quite fit. That's why we made one of our own. BrowserDo MCP + Embiody Browser 0.9 Preview has been in closed beta for two…

  • Embiody 0.9 Preview introduces browser for AI agents to work alongside humans
  • IA tabs function maintains full operation even when running in background
  • Anti-bot blocking system prevents browser from being flagged as bot

I got tired of Redis and Kafka eating my RAM, so I rebuilt them in Rust hitting 1.6M RPS (as a student)

Hey everyone, I’m Yasir. I’m an 18-year-old software engineering student from Pakistan, and for the last few months, I’ve been going down a very deep, very complex rabbit hole: Systems Programming in…

  • 18-year-old Pakistani student builds custom message queue and in-memory store in Rust
  • Velocity-MQ and VelocityDB architectures enable 1.6M RPS performance
  • First-semester CS student seeks community feedback and contributions

Docker COPY --from stage not found in CI

A docker COPY --from stage not found does not produce a message about stages, because BuildKit does not treat an unknown name as a mistake.

  • Docker COPY --from stage not found in CI, treated as image reference
  • BuildKit searches for unknown name in registry instead of treating as mistake
  • Numeric index provides explicit error, stage name causes silent registry trip

More from Sunday 15 November →