RP ID and origins
Every demo so far has quietly relied on one fact: a passkey is scoped to an RP ID, not to the exact origin it was created on. RP ID must be the origin's hostname, or a registrable domain suffix of it — a less specific parent domain, never a more specific child. That single rule is both why passkeydemo.com and its subdomains can share credentials, and why nothing else on the internet can.
This site's server always uses passkeydemo.com as the RP ID (see
shared/src/environments.ts's allowlist) whether a request arrives
from the main site or from sandbox.passkeydemo.com — a subdomain
that exists solely so this page has a second real origin to demonstrate with.
1. A credential registered here works from the sandbox subdomain too
This is the same discoverable-credential flow from the Discoverable credentials page — the point here isn't the ceremony, it's where it works. The credential is scoped to the RP ID, and the RP ID is the same on both origins.
Sign in (works on either origin)
2. A mismatched RP ID fails before the authenticator is even asked
The reverse direction — a subdomain claiming its parent's child as an
RP ID — isn't a registrable suffix of the current origin, so
navigator.credentials.create() rejects synchronously with a
SecurityError. No network round trip, no authenticator prompt; the
browser refuses before anything else happens.