Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds Related Origin Requests #2040

Merged
merged 32 commits into from
Jul 17, 2024
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0522807
initial text
timcappalli Mar 12, 2024
d48a18c
remaining draft text
timcappalli Mar 12, 2024
2a18351
s/webauthn-origins/webauthn
timcappalli Mar 13, 2024
689647c
MUST support 5 origin labels
timcappalli Mar 13, 2024
3aad054
s/member/property, s/list/array
timcappalli Mar 13, 2024
5187e72
use [=continue=]
timcappalli Mar 26, 2024
881ac8f
collapse multiple steps into one
timcappalli Mar 26, 2024
9062a15
s/vanity/alternative
timcappalli Mar 26, 2024
2315db8
capitalization
timcappalli Mar 26, 2024
8ea0303
s/relatedOriginRequests/relatedOrigins
timcappalli Mar 26, 2024
28a2b0f
attempt at using a procedure
timcappalli Mar 26, 2024
b51bd16
s/must/MUST
timcappalli Mar 26, 2024
a21babf
remove break
timcappalli Apr 29, 2024
7466f32
remove break for create
timcappalli Apr 29, 2024
e7d0c7c
s/originLabelsSeen/labelsSeen and set def
timcappalli Apr 29, 2024
b3bf34c
word order
timcappalli Apr 29, 2024
bdba742
Validation step optimization
timcappalli Apr 29, 2024
de25c37
use macros for true and false
timcappalli Apr 29, 2024
71e4e80
add period
timcappalli Jun 12, 2024
26d350c
text tweak
timcappalli Jun 12, 2024
a2ac319
clean up well-known JSON definition
timcappalli Jun 14, 2024
b120220
s/origin labels/labels
timcappalli Jun 14, 2024
bcec7fa
s/rpIdRequested/callerOrigin
timcappalli Jun 14, 2024
3ba2ff3
move set contains label check after origin match check
timcappalli Jun 14, 2024
a108a2c
add RP guidance around adding all origins with the same origin label …
timcappalli Jun 14, 2024
c0c40d1
remove check for label in labelsSeen, not necessary
timcappalli Jun 14, 2024
ebf03eb
fix indents
timcappalli Jun 14, 2024
e4f24d9
update RWO algo to support additional origins with the same label
timcappalli Jun 26, 2024
2e9bdcf
remove consideration text for RPs about RWO well-known ordering
timcappalli Jun 26, 2024
2462fd8
Emil's feedback
timcappalli Jul 17, 2024
9da2c4b
procedure dfn
timcappalli Jul 17, 2024
017a5e3
Editorial tweaks
timcappalli Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 105 additions & 13 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,12 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
: <dfn>Non-Discoverable Credential</dfn>
:: This is a [=credential=] whose [=credential ID=] must be provided in {{PublicKeyCredentialRequestOptions/allowCredentials}} when calling {{CredentialsContainer/get()|navigator.credentials.get()}} because it is not [=client-side discoverable credential|client-side discoverable=]. See also [=server-side credentials=].

: <dfn>Registrable Origin Label</dfn>
:: The first [=domain label=] of the [=registrable domain=] of a [=domain=],
or null if the [=registrable domain=] is null.
For example, the [=registrable origin label=] of both `example.co.uk` and `www.example.de` is `example`
if both `co.uk` and `de` are [=public suffixes=].

: <dfn>Public Key Credential</dfn>
:: Generically, a *credential* is data one entity presents to another in order to *authenticate* the former to the latter
[[RFC4949]]. The term [=public key credential=] refers to one of: a [=public key credential source=], the
Expand Down Expand Up @@ -1824,11 +1830,21 @@ a numbered step. If outdented, it (today) is rendered as a bullet in the midst o

: is present
:: If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> [=is not a
registrable domain suffix of and is not equal to=] |effectiveDomain|, throw a "{{SecurityError}}" {{DOMException}}.
registrable domain suffix of and is not equal to=] |effectiveDomain|, and if the client

<dl class="switch">
: supports [[#sctn-related-origins|related origin requests]]
:: 1. Let |rpIdRequested| be the value of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code>.
emlun marked this conversation as resolved.
Show resolved Hide resolved

: Is not present
:: Set <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> to
|effectiveDomain|.
1. Run the [$related origins validation procedure$] with arguments |callerOrigin| and |rpIdRequested|.
If the result is [FALSE], throw a "{{SecurityError}}" {{DOMException}}.

: does not support [[#sctn-related-origins|related origin requests]]
:: throw a "{{SecurityError}}" {{DOMException}}.
</dl>

: is not present
:: Set <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> to |effectiveDomain|.
</dl>

Note: <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> represents the
Expand Down Expand Up @@ -2314,19 +2330,31 @@ When this method is invoked, the user agent MUST execute the following algorithm
PKI-based security.

<li id='GetAssn-DetermineRpId'>
If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> is not present, then set |rpId| to
|effectiveDomain|.
If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code>
<dl class="switch">

Otherwise:
: is present
:: If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> [=is not a
registrable domain suffix of and is not equal to=] |effectiveDomain|, and if the client

1. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> [=is not a registrable domain suffix of and is not
equal to=] |effectiveDomain|, throw a "{{SecurityError}}" {{DOMException}}.
<dl class="switch">
: supports [[#sctn-related-origins|related origin requests]]
:: 1. Let |rpIdRequested| be the value of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code>

1. Run the [$related origins validation procedure$] with arguments |callerOrigin| and |rpIdRequested|.
If the result is [FALSE], throw a "{{SecurityError}}" {{DOMException}}.

1. Set |rpId| to <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code>.
: does not support [[#sctn-related-origins|related origin requests]]
:: throw a "{{SecurityError}}" {{DOMException}}.
</dl>

Note: |rpId| represents the caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment
settings object/origin=]'s [=effective domain=] unless the caller has explicitly set
<code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> when calling {{CredentialsContainer/get()}}.
: is not present
:: Set <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> to |effectiveDomain|.
</dl>

Note: |rpId| represents the caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment
settings object/origin=]'s [=effective domain=] unless the caller has explicitly set
<code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> when calling {{CredentialsContainer/get()}}.
</li>

1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=].
Expand Down Expand Up @@ -3963,6 +3991,7 @@ Note: The {{UserVerificationRequirement}} enumeration is deliberately not refere
"hybridTransport",
"passkeyPlatformAuthenticator",
"userVerifyingPlatformAuthenticator",
"relatedOrigins"
};
</xmp>

Expand All @@ -3985,6 +4014,9 @@ Note: The {{ClientCapability}} enumeration is deliberately not referenced, see [

: <dfn>userVerifyingPlatformAuthenticator</dfn>
:: The [=WebAuthn Client=] supports usage of a [=user-verifying platform authenticator=].

: <dfn>relatedOrigins</dfn>
:: The [=WebAuthn Client=] supports [[#sctn-related-origins|Related Origin Requests]].
</div>

### User-agent Hints Enumeration (enum <dfn enum>PublicKeyCredentialHints</dfn>) ### {#enum-hints}
Expand Down Expand Up @@ -4046,7 +4078,62 @@ To override this default policy and indicate that a cross-origin <{iframe}> is a

[=[RPS]=] utilizing the WebAuthn API in an embedded context should review [[#sctn-seccons-visibility]] regarding [=UI redressing=] and its possible mitigations.

## Using Web Authentication across related origins ## {#sctn-related-origins}

By default, Web Authentication requires that the [=RP ID=] be equal to the [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=], or a [=is a registrable domain suffix of or is equal to|registrable domain suffix=] of the [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=].

This can make deployment challenging for large environments where multiple country-specific domains are in use (e.g. example.com vs example.co.uk vs example.sg), where alternative or brand domains are required (e.g. myexampletravel.com vs examplecruises.com), and/or where platform as a service providers are used to support mobile apps.

[=[WRPS]=] can opt in to allowing [=WebAuthn Clients=] to enable a credential to be created and used across a limited set of related [=origin|origins=].
Such [=[RPS]=] MUST choose a common [=RP ID=] to use across all ceremonies from related origins.

A JSON document MUST be hosted at the `webauthn` well-known URL [[!RFC8615]] for the [=RP ID=]. The JSON document MUST be returned as follows:

- The content type MUST be `application/json`.
- The top-level JSON object MUST contain a key named `origins` whose value MUST be an array of one or more strings containing web origins.

For example, for the RP ID `example.com`:

<xmp class="json" highlight="json">
{
"origins": [
"https://example.co.uk",
"https://example.de",
"https://example.sg",
"https://example.net",
"https://exampledelivery.com",
"https://exampledelivery.co.uk",
"https://exampledelivery.de",
"https://exampledelivery.sg",
"https://myexamplerewards.com",
"https://examplecars.com"
]
}
</xmp>

[=WebAuthn Clients=] supporting this feature MUST support at least five [=registrable origin labels=]. Client policy SHOULD define an upper limit to prevent abuse.

[=WebAuthn Clients=] supporting this feature SHOULD include {{ClientCapability/relatedOrigins}} in their response to [[#sctn-getClientCapabilities|getClientCapabilities()]].

### Validating Related Origins ### {#sctn-validating-relation-origin}

The <dfn abstract-op>related origins validation procedure</dfn>, given arguments |callerOrigin| and |rpIdRequested|, is as follows:

1. Let |maxLabels| be the maximum number of [=registrable origin labels=] allowed by client policy.
1. Fetch the `webauthn` well-known URL [[!RFC8615]] for the RP ID |rpIdRequested| (i.e., <code>https://|rpIdRequested|/.well-known/webauthn</code>).
1. If the fetch fails, the response does not have a content type of `application/json`, or does not have a status code (after following redirects) of 200, then throw a "{{SecurityError}}" {{DOMException}}.
1. If the body of the resource is not a valid JSON object, then throw a "{{SecurityError}}" {{DOMException}}.
1. If the value of the |origins| property of the JSON object is missing, or is not an array of strings, then throw a "{{SecurityError}}" {{DOMException}}.
timcappalli marked this conversation as resolved.
Show resolved Hide resolved
1. Let |labelsSeen| be a new empty [=set=].
1. [=set/For each=] |originItem| of |origins|:
1. Let |url| be the result of running the [=URL parser=] with |originItem| as the input. If that fails, [=continue=].
1. Let |domain| be the [=effective domain=] of |url|. If that is null, [=continue=].
1. Let |label| be [=registrable origin label=] of |domain|.
1. If |label| is empty or null, [=continue=].
1. If the [=set/size=] of |labelsSeen| is greater than or equal to |maxLabels| and |labelsSeen| does not [=set/contain=] |label|, [=continue=].
1. If |callerOrigin| and |url| are [=same origin=], return [TRUE].
1. If the [=set/size=] of |labelsSeen| is less than |maxLabels|, [=set/append=] |label| to |labelsSeen|.
1. Return [FALSE].

# WebAuthn <dfn>Authenticator Model</dfn> # {#sctn-authenticator-model}

Expand Down Expand Up @@ -8616,6 +8703,11 @@ For example:
{{CollectedClientData/origin}} to exactly equal some element of a list of allowed origins,
for example the list <code>["https://example.org", "https://login.example.org"]</code>.

- A web application leveraging [[#sctn-related-origins|related origin requests]] might also require
{{CollectedClientData/origin}} to exactly equal some element of a list of allowed origins,
for example the list <code>["https://example.co.uk", "https://example.de", "https://myexamplerewards.com"]</code>.
This list will typically match the origins listed in the well-known URI for the [=RP ID=]. See [[#sctn-related-origins]].

- A web application served at a large set of domains that changes often might parse
{{CollectedClientData/origin}} structurally and require that the URL scheme is <code>https</code>
and that the authority equals or is any subdomain of the [=RP ID=] - for example,
Expand Down