RP ID Strategy for Multi-Domain Apps

The RP ID decides which of your surfaces share credentials, and it is effectively permanent — a credential is bound to the value in force when it was created. This page covers how to choose it from your account model rather than from your DNS layout, what widening it later actually costs, and how related origins change the picture for multi-domain brands. It sits under Relying Party and Authenticator Roles, where the suffix rule itself is defined.


Constraint Reference

Constraint Rule Consequence
Suffix relationship the RP ID must equal the page’s effective domain or be a registrable parent a child RP ID on a parent page is refused
Public suffix boundary the RP ID cannot be a public suffix hosts on *.pages.dev and similar cannot widen
Binding at creation fixed for the life of the credential widening strands existing credentials
Per-origin visibility credentials are offered only for a matching RP ID separate RP IDs mean separate account silos

The first two are enforced by the browser and produce a SecurityError. The last two are not errors at all — they are silent consequences that surface as “my passkey has disappeared”.

Four estate shapes, four answers The right RP ID depends on whether your surfaces are one product, several products, or several brands. Decide from the account model, not from the DNS tree one product, many subdomains a single RP ID at the shared registrable domain several products, one brand still one RP ID if users expect one account separate brands, separate accounts one RP ID per brand — the isolation is intentional a public-suffix host no widening is possible; each host is its own relying party

Root Cause Analysis

1. Choosing from the DNS tree rather than the account model. The question is not which domains you own, it is which surfaces share an account. If a user has one account across app.example.com and accounts.example.com, those surfaces must share one RP ID, and the shared registrable domain is the only value that works.

2. Starting narrow and planning to widen. This is the decision that cannot be undone. Every credential enrolled under app.example.com becomes invisible the moment you deploy example.com, and the only recovery is mass re-enrolment through the recovery flow — which is both slower and weaker than the credential you just invalidated.

3. Hosting on a public suffix. Preview and static-hosting platforms frequently place each deployment on a host whose registrable domain is the whole host. Credentials on such a host cannot be shared with anything, and each preview deployment is its own relying party. This is fine for previews and fatal if it reaches production.

4. Deriving the RP ID from the request. A service that reads the value from an incoming header will build ceremony options for whatever a proxy or an attacker put there. Pin the value in configuration, per environment.

What widening later would cost A credential is bound to the RP ID in force when it was created, so broadening the value strands everything already enrolled. There is no migration path — only re-enrolment credentials exist under the narrow RP ID RP ID widened new value deployed old credentials no longer offered every user must re-enrol Which is why this is one of the few WebAuthn decisions that is genuinely expensive to revisit.

Step-by-Step Resolution

Step 1 — enumerate the surfaces that share an account

List every origin from which a user of one account may sign in. If the list spans several subdomains of one registrable domain, the answer is that domain.

Step 2 — check the public suffix boundary

Confirm your chosen value is not itself a public suffix, and that every listed origin is a subdomain of it. Preview hosts frequently fail this check.

Step 3 — pin it per environment

Production, staging and local development each need their own configured value, validated at process start. A service whose RP ID is not a suffix of every allowed origin should refuse to boot.

Step 4 — separate brands deliberately

Where two products genuinely have separate accounts, separate RP IDs are the correct choice and the resulting isolation is a feature. Document that decision so a future engineer does not “fix” it.

Step 5 — treat related origins as an enhancement

Where one brand spans unrelated domains, a related-origins configuration can let them share an RP ID. Support is uneven, so design the account model to work without it and let it improve the experience where available.

Related origins, and what they do not solve A related-origin mechanism lets one RP ID span unrelated domains, but it does not merge separately enrolled credentials. Useful for multi-domain brands, not a retrofit related origins can let one RP ID be claimed from another domain serve a brand with several country domains avoid duplicate enrolment for new users related origins cannot merge credentials enrolled under two RP IDs change an existing credential’s binding remove the need to pick a canonical RP ID Support varies by client, so treat it as an enhancement rather than as the foundation of your account model.

Verification and Testing

Assert the suffix relationship in a unit test that reads your real configuration. For each environment, every allowed origin must be equal to or a subdomain of the configured RP ID; anything else is a deployment that cannot work.

Add a synthetic ceremony per production surface. A headless run that completes a registration and an assertion on each sign-in origin catches the case where a new surface was added to the estate and nobody updated the allow-list or checked the suffix relationship.

For a multi-brand estate, add a negative test: a credential enrolled under one RP ID must not be offered on a surface using the other. That test documents the intended isolation in a form that survives refactoring.


Pitfalls

1. Using a preview hostname in production configuration. It works in preview and silos every credential.

2. Widening after launch. There is no migration; there is only re-enrolment.

3. Assuming related origins are universally supported. Design for the case where they are not.


Frequently Asked Questions

Can two RP IDs share one user account internally?

Yes, and it is sometimes the pragmatic answer during a transition: your database links both credentials to one account even though the authenticator treats them as separate relying parties. The user still has to enrol twice, and the sign-in surface must know which RP ID to request, but nothing about the account model forces a split.

Does the RP ID affect the origin check?

No — they are separate checks with different rules. The origin is compared as an exact string against an allow-list; the RP ID is compared with a suffix rule. Both must pass, and treating either as a substitute for the other produces a false rejection or a real weakness.

What should development use?

localhost, which is a secure context without TLS and is its own registrable domain. Avoid LAN addresses, which are neither, and avoid sharing the production RP ID with a development surface, which would let a development origin claim production credentials if the allow-list ever slipped.

Can I use a country-code domain as the RP ID for all locales?

Only if every locale surface is a subdomain of it, which is usually not the case for example.de and example.fr. That is precisely the shape related origins exist to serve; without them, either pick one canonical domain and serve all locales beneath it, or accept per-locale credential silos.

How do native apps fit into this?

Through the platform’s associated-domains mechanism, which links an application to a domain so that credentials created for that RP ID are available in the app. The RP ID stays the web domain; the app does not get one of its own, and this is another reason to choose the value carefully at the outset.

Is there any reason to prefer a narrow RP ID?

Only genuine isolation — a product whose accounts must not be interchangeable with a sibling’s. If the two products share a login, a narrow RP ID gives you all of the costs of separation and none of its benefits.


How do acquisitions and rebrands affect this?

They are the situation where the permanence bites hardest. Acquiring a product with its own RP ID leaves you with two credential silos and no way to merge them, so the realistic plan is to keep both working, enrol new credentials under whichever RP ID the combined account model settles on, and retire the other over a period measured in quarters rather than sprints. Rebranding to a new domain has the same shape and the same answer: run both, prompt for a new credential after a successful sign-in, and let the old value expire with the accounts that still depend on it.

Related