What an RP ID actually controls

The relying party ID (RP ID) is a domain string that defines the boundary within which a WebAuthn credential — such as a passkey — can be used. When a passkey is created, the browser binds it to the RP ID you specify. On subsequent authentication attempts, the browser checks the requesting origin against that RP ID and refuses to release the credential if the origin doesn't match or fall within the RP ID's scope.

An RP ID must be a valid domain string. It can be either the exact current hostname or a broader parent domain, as long as that broader domain is an eTLD+1 or higher. IP addresses and public suffixes (eTLDs) are not allowed as RP IDs.

Choosing the right scope for your domain

Whether you can use a particular RP ID depends on the origin hosting your service. For a server at https://www.example.com, both example.com and www.example.com are permissible RP IDs; the right choice depends on how widely you want the passkey to roam.

If you register a passkey under the broader eTLD+1 (example.com), it will work on any subdomain — for example, both https://login.example.com and https://shop.example.com. Choosing a more specific RP ID such as login.example.com restricts the passkey to that exact origin; it will not work on https://shop.example.com.

Origin host Permissible RP ID (eTLD+1)
https://login.example.com example.com or login.example.com
https://example.com:8080 example.com (port numbers are excluded)
https://mobile.example.co.jp example.co.jp or mobile.example.co.jp
https://sub.project.org.uk project.org.uk or sub.project.org.uk
https://user.github.io user.github.io (github.io is an eTLD)
https://myapp.pages.dev myapp.pages.dev (pages.dev is an eTLD)
http://localhost localhost (an exception to the HTTPS requirement)

This scoping works because passkeys are cryptographically tied to the RP ID at creation time, and the origin of any future authentication request must correspond to that RP ID for the credential to be released.

Sharing passkeys across distinct sites

Standard RP IDs cannot bridge services that live on different eTLD+1s. If your product spans, say, example.com and example.co.jp, that's a cross-site configuration, and WebAuthn's default behavior won't let users carry a single passkey between them.

Related Origin Requests (ROR) exists for exactly this scenario. ROR lets a browser recognize different origins as parts of the same logical service, so a passkey created on one site can be used on another.

Implementing ROR requires three things:

  • A single RP ID — choose one RP ID and reuse it across all participating sites.
  • A hosted configuration file — the primary RP ID domain must serve a file at /.well-known/webauthn listing the authorized origins.
  • Consistent calls — the rpId passed in the WebAuthn call must be the primary RP ID on every site, during both creation and authentication. A user on https://www.example.co.jp still uses example.com as the rpId.

For an RP ID of example.com, the configuration file lives at https://example.com/.well-known/webauthn:

{
  "origins": [
    "https://www.example.co.jp",
    "https://shop.example"
  ]
}

Extending RP IDs to mobile apps

Native mobile apps can use passkeys tied to your web domain, but only after you establish a verifiable relationship between the app and the domain. That relationship is proven through platform-specific files you host on your server.

Android's Credential Manager requires a Digital Asset Link (DAL) file served from the RP ID domain to associate your app with that domain.

  • File location: https://<RP ID>/.well-known/assetlinks.json
  • Verification: the origin in clientDataJSON must be validated. On Android this appears as android:apk-key-hash:<hash>.

For an RP ID of example.com, the DAL file is hosted at https://example.com/.well-known/assetlinks.json:

[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls",
      "delegate_permission/common.get_login_creds"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.google.credentialmanager.sample",
      "sha256_cert_fingerprints": [
        "4F:20:47:1F:D9:9A:BA:96:47:8D:59:27:C2:C8:A6:EA:8E:D2:8D:14:C0:B6:A2:39:99:9F:A3:4D:47:3D:FA:11"
      ]
    }
  }
]

iOS and Associated Domains

Apple platforms use an apple-app-site-association (AASA) file on the RP ID domain for the same purpose.

  • File location: https://<RP_ID>/.well-known/apple-app-site-association
  • Entitlements: add webcredentials:<app info> to your app's entitlements.

The AASA file for example.com would be at https://example.com/.well-known/apple-app-site-association:

{
  "webcredentials":
    {
      "apps": ["EXAMPLE123.com.example.passkey"]
    }
}

Key takeaways

  • Pick your RP ID scope deliberately: an eTLD+1 like example.com covers all subdomains, while a hostname like login.example.com covers only that exact origin.
  • For services spread over multiple eTLD+1s, ROR is the mechanism — one shared RP ID plus a /.well-known/webauthn configuration file.
  • Mobile passkey support depends on verified domain association: a DAL file at /.well-known/assetlinks.json for Android, and an AASA file at /.well-known/apple-app-site-association for iOS.