From ee91210eeafd66cc5fe67fc80b68b6cbc64b6e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Thu, 25 Jul 2024 02:33:56 +1000 Subject: [PATCH 1/3] Use credential type registry for permissions + digital credentials (#242) --- index.bs | 96 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/index.bs b/index.bs index f803ea6..9ab97b5 100644 --- a/index.bs +++ b/index.bs @@ -98,20 +98,15 @@ spec:css-syntax-3;
 {
-  "FEDCM": {
-    "authors": [ "Sam Goto" ],
-    "href": "https://fedidcg.github.io/FedCM/",
-    "title": "FedCM API"
-  },
   "WEB-LOGIN": {
     "authors": [ "Jason Denizac", "Robin Berjon", "Anne van Kesteren" ],
     "href": "https://github.com/jden/web-login",
     "title": "web-login"
   },
-  "WEB-OTP": {
-    "authors": [ "Sam Goto" ],
-    "href": "https://wicg.github.io/web-otp/",
-    "title": "WebOTP API"
+  "DIGITAL-CREDENTIALS": {
+    "authors": [ "Marcos Cáceres", "Sam Goto" ],
+    "href": "https://wicg.github.io/digital-credentials/",
+    "title": "Digital Credentials"
   }
 }
 
@@ -325,14 +320,27 @@ spec:css-syntax-3; (in alphabetical order) Options Member Identifier Appropriate Interface Object + Get Permissions Policy + Create Permissions Policy Specification Requestor Contact + + digital-credential + digital + {{DigitalCredential}} + digital-credentials-get + null + [[DIGITAL-CREDENTIALS]] + WICG + federated federated {{FederatedCredential}} + null + null This specification: [[#federated]] W3C @@ -340,6 +348,8 @@ spec:css-syntax-3; identity identity {{IdentityCredential}} + [=identity-credentials-get=] + null [[FEDCM]] W3C @@ -347,6 +357,8 @@ spec:css-syntax-3; otp otp {{OTPCredential}} + [=otp-credentials-feature|otp-credentials=] + null [[WEB-OTP]] WICG @@ -354,6 +366,8 @@ spec:css-syntax-3; password password {{PasswordCredential}} + null + null This specification: [[#passwords]] W3C @@ -361,6 +375,8 @@ spec:css-syntax-3; public-key publicKey {{PublicKeyCredential}} + [=publickey-credentials-get-feature|publickey-credentials-get=] + [=publickey-credentials-create-feature|publickey-credentials-create=] [[WEBAUTHN]] W3C @@ -382,6 +398,14 @@ spec:css-syntax-3; * Each registry entry must state the [=credential type registry/Appropriate Interface Object=] [=identifier=] for the [=credential type registry/credential type=]. + * Each registry entry must state the [=credential type registry/Get Permissions Policy=] [=permission=] + used when executing Request a `Credential` for a + [=credential type registry/credential type=], or null if no [=Document/permissions policy=] is specified. + + * Each registry entry must state the [=credential type registry/Create Permissions Policy=] [=permission=] + used when executing Create a `Credential` for a + [=credential type registry/credential type=], or null if no [=Document/permissions policy=] is specified. + * Each registry entry must include a link that references a publicly available specification defining the [=credential type registry/credential type=] and the [=dictionary member=] [=identifier=]. @@ -950,8 +974,10 @@ spec:css-syntax-3; 1. Assert: |settings| is a [=secure context=]. - 1. If |settings|'s [=relevant global object=]'s [=associated Document=] is not [=Document/fully active=], - then return [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. + 1. Let |document| be |settings|'s [=relevant global object=]'s [=associated Document=]. + + 1. If |document| is not [=Document/fully active=], then return [=a promise rejected with=] + "{{NotAllowedError}}" {{DOMException}}. 1. If |options|.{{CredentialRequestOptions/signal}} is [=AbortSignal/aborted=], then return [=a promise rejected with=] @@ -965,8 +991,6 @@ spec:css-syntax-3; 1. If |interface| does not support {{CredentialMediationRequirement/conditional}} [=user mediation=], return [=a promise rejected with=] a "{{TypeError}}" {{DOMException}}. - 1. Let |p| be [=a new promise=]. - 1. For each |interface| in |options|' relevant credential interface objects: 1. If |settings|' [=active credential types=] [=set/contains=] |interface|'s @@ -983,21 +1007,16 @@ spec:css-syntax-3; 1. Let |sameOriginWithAncestors| be `true` if |settings| is [=same-origin with its ancestors=], and `false` otherwise. - 1. If |options|[{{CredentialRequestOptions/identity}}] [=map/exists=] and - if |settings|' [=relevant global object=]'s [=associated Document=] is **not** - [=allowed to use=] the [=identity-credentials-get=] - [=policy-controlled feature=] return [=a promise rejected with=] a "{{NotAllowedError}}" - {{DOMException}}. + 1. For each |interface| in |options|' [=relevant credential interface objects=]: - 1. If |options|[{{CredentialRequestOptions/publicKey}}] [=map/exists=] and - if |settings|' [=relevant global object=]'s [=associated Document=] is **not** - [=allowed to use=] the [=publickey-credentials-get-feature|publickey-credentials-get=] - [=policy-controlled feature=] return [=a promise rejected with=] a "{{NotAllowedError}}" - {{DOMException}}. + 1. Let |permission| be the |interface|'s {{Credential/[[type]]}} [=credential type registry/Get Permissions Policy=]. - Note: `password` and `federated` - [=credential type registry/credential types=] are not presently treated as - [=policy-controlled features=], although this may change in the future. + 1. If |permission| is null, continue. + + 1. If |document| is **not** [=allowed to use=] |permission|, return + [=a promise rejected with=] a "{{NotAllowedError}}" {{DOMException}}. + + 1. Let |p| be [=a new promise=]. 1. Run the following steps [=in parallel=]: @@ -1164,22 +1183,14 @@ spec:css-syntax-3; 1. Let |global| be |settings|' [=environment settings object/global object=]. - 1. If |settings|'s [=relevant global object=]'s [=associated Document=] is not [=Document/fully active=], - then return [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. + 1. Let |document| be the [=relevant global object=]'s [=associated Document=]. + + 1. If |document| is not [=Document/fully active=], then return + [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. 1. Let |sameOriginWithAncestors| be `true` if the [=current settings object=] is [=same-origin with its ancestors=], and `false` otherwise. - 1. If |options|[{{CredentialCreationOptions/publicKey}}] [=map/exists=] and - if |settings|' [=relevant global object=]'s [=associated Document=] is **not** - [=allowed to use=] the [=publickey-credentials-create-feature|publickey-credentials-create=] - [=policy-controlled feature=] return [=a promise rejected with=] a "{{NotAllowedError}}" - {{DOMException}}. - - Note: `password` and `federated` - [=credential type registry/credential types=] are not presently treated as - [=policy-controlled features=], although this may change in the future. - 1. Let |interfaces| be the [=set=] of |options|' relevant credential interface objects. 1. Return [=a promise rejected with=] `NotSupportedError` if any of the following statements @@ -1194,6 +1205,15 @@ spec:css-syntax-3; types in order to support a "sign-up" use case. For the moment, though, we're punting on that by restricting the dictionary to a single entry. + 1. For each |interface| in |interfaces|: + + 1. Let |permission| be the |interface|'s {{Credential/[[type]]}} [=credential type registry/Create Permissions Policy=]. + + 1. If |permission| is null, continue. + + 1. If |document| is **not** [=allowed to use=] |permission|, return + [=a promise rejected with=] a "{{NotAllowedError}}" {{DOMException}}. + 1. If |options|.{{CredentialRequestOptions/signal}} is [=AbortSignal/aborted=], then return [=a promise rejected with=] |options|.{{CredentialRequestOptions/signal}}'s [=AbortSignal/abort reason=]. From 7fb261af15ec9fb94a502735fb1b86a2554bcdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Fri, 26 Jul 2024 17:07:51 +1000 Subject: [PATCH 2/3] Editorial: fix small bs syntax mistakes (#246) --- index.bs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 9ab97b5..a933f28 100644 --- a/index.bs +++ b/index.bs @@ -811,7 +811,7 @@ spec:css-syntax-3; see a [=credential chooser=] if necessary. : conditional - :: For {CredentialsContainer/get()}, discovered credentials are presented to the user in a non-modal dialog along with an + :: For {{CredentialsContainer/get()}}, discovered credentials are presented to the user in a non-modal dialog along with an indication of the [=origin=] which is requesting credentials. If the user makes a gesture outside of the dialog, the dialog closes without resolving or rejecting the {{Promise}} returned by the {{CredentialsContainer/get()}} method and without causing a user-visible @@ -830,7 +830,7 @@ spec:css-syntax-3; interfaces it refers to=] have overridden {{Credential/isConditionalMediationAvailable()}} to return a new {{Promise}} that [=resolves=] with `true`. - For {CredentialsContainer/create()}, if a user has previously consented to credential creation and + For {{CredentialsContainer/create()}}, if a user has previously consented to credential creation and the user agent knows it recently mediated an authentication, then the `create()` call may resolve without additional prominent modal interaction. If the user agent did not recently mediate an authentication or does not have consent for credential creation, then the call must throw a "{{NotAllowedError}}" {{DOMException}}. @@ -2136,17 +2136,17 @@ spec:css-syntax-3; When responding to a call to {{CredentialsContainer/get()}} on an origin which requires [=user mediation=], user agents MUST ask the user for permission to share credential information. - This SHOULD take the form of a credential chooser which presents the user with a + This SHOULD take the form of a credential chooser which presents the user with a list of credentials that are available for use on a site, allowing them to select one which should - be provided to the website, or to reject the request entirely. + be provided to the website, or to abort the request entirely. - The chooser interface SHOULD be implemented in such a way as to be distinguishable from UI which a + The [=chooser's=] user interface SHOULD be implemented in such a way as to be distinguishable from UI which a website could produce. For example, the chooser might overlap the user agent's UI in some unspoofable way. - The chooser interface MUST include an indication of the origin which is requesting credentials. + The [=chooser's=] user interface MUST include an indication of the origin which is requesting credentials. - The chooser interface SHOULD include all {{Credential}} objects associated with the origin that + The [=chooser's=] user interface SHOULD include all {{Credential}} objects associated with the origin that requested credentials. User agents MAY internally associate information with each {{Credential}} object beyond the @@ -2154,7 +2154,7 @@ spec:css-syntax-3; example, favicons could help disambiguate identity providers, etc. Any additional information stored MUST not be exposed directly to the web. - The chooser's behavior is not defined here: user agents are encouraged to experiment with UI + The [=chooser's=] behavior is not defined here: user agents are encouraged to experiment with UI treatments that educate users about their authentication options, and guide them through the process of choosing a credential to present. That said, the interface to the chooser is as follows: From 991c1ecef9f4e0e51803df0dd91a89b110e7e052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A1ceres?= Date: Sat, 27 Jul 2024 05:32:34 +1000 Subject: [PATCH 3/3] Use 'InvalidStateError' for fully active check (#245) --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index a933f28..a5e5410 100644 --- a/index.bs +++ b/index.bs @@ -977,7 +977,7 @@ spec:css-syntax-3; 1. Let |document| be |settings|'s [=relevant global object=]'s [=associated Document=]. 1. If |document| is not [=Document/fully active=], then return [=a promise rejected with=] - "{{NotAllowedError}}" {{DOMException}}. + an "{{InvalidStateError}}" {{DOMException}}. 1. If |options|.{{CredentialRequestOptions/signal}} is [=AbortSignal/aborted=], then return [=a promise rejected with=] @@ -1130,7 +1130,7 @@ spec:css-syntax-3; 1. Assert: |settings| is a [=secure context=]. 1. If |settings|'s [=relevant global object=]'s [=associated Document=] is not [=Document/fully active=], - then return [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. + then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. 1. Let |sameOriginWithAncestors| be `true` if the [=current settings object=] is [=same-origin with its ancestors=], and `false` otherwise. @@ -1186,7 +1186,7 @@ spec:css-syntax-3; 1. Let |document| be the [=relevant global object=]'s [=associated Document=]. 1. If |document| is not [=Document/fully active=], then return - [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. + [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. 1. Let |sameOriginWithAncestors| be `true` if the [=current settings object=] is [=same-origin with its ancestors=], and `false` otherwise. @@ -1271,7 +1271,7 @@ spec:css-syntax-3; 1. Let |origin| be |settings|' [=environment settings object/origin=]. 1. If |settings|'s [=relevant global object=]'s [=associated Document=] is not [=Document/fully active=], - then return [=a promise rejected with=] "{{NotAllowedError}}" {{DOMException}}. + then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. 2. Let |p| be [=a new promise=]