From 00126ee61819c3eb8fe823d96395a238ba531e7e Mon Sep 17 00:00:00 2001 From: marcoscaceres Date: Fri, 5 Jul 2024 14:54:08 +1000 Subject: [PATCH] Digital Credentials: implement digital-credentials-get permission policy https://bugs.webkit.org/show_bug.cgi?id=275783 rdar://130821690 Reviewed by NOBODY (OOPS!). Implements the digital-credentials-get permission policy directive. This directive allows a site to control whether the .get() method can be used in the Digital Credential API. Related spec change: https://github.com/WICG/digital-credentials/pull/132 * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers: Added. * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/iframe.html: Added. * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html: Added. * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js: (test_feature_availability): * Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp: (WebCore::IdentityCredentialsContainer::get): * Source/WebCore/html/PermissionsPolicy.cpp: (WebCore::toFeatureNameForLogging): (WebCore::readFeatureIdentifier): (WebCore::defaultAllowlistValue): * Source/WebCore/html/PermissionsPolicy.h: * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: --- .../allow-attribute.https-expected.txt | 14 ++ .../allow-attribute.https.html | 124 ++++++++++++++++++ ...-permissions-policy.https.sub-expected.txt | 3 + .../default-permissions-policy.https.sub.html | 42 ++++++ ...-permissions-policy.https.sub-expected.txt | 5 + ...abled-by-permissions-policy.https.sub.html | 36 +++++ ...-permissions-policy.https.sub.html.headers | 1 + ...-permissions-policy.https.sub-expected.txt | 6 + ...rigin-by-permissions-policy.https.sub.html | 59 +++++++++ ...-permissions-policy.https.sub.html.headers | 1 + ...-permissions-policy.https.sub-expected.txt | 5 + ...override-permissions-policy.https.sub.html | 39 ++++++ ...-permissions-policy.https.sub.html.headers | 1 + .../digital-credentials/support/iframe.html | 69 ++++++++++ .../resources/digital-credentials-get.html | 33 +++++ .../resources/permissions-policy.js | 9 +- .../identity/IdentityCredentialsContainer.cpp | 6 + Source/WebCore/html/PermissionsPolicy.cpp | 7 + Source/WebCore/html/PermissionsPolicy.h | 1 + .../WebCoreArgumentCoders.serialization.in | 1 + 20 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https-expected.txt create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers create mode 100644 LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/iframe.html create mode 100644 LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https-expected.txt new file mode 100644 index 0000000000000..483c029765b1d --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https-expected.txt @@ -0,0 +1,14 @@ + +PASS Policy to use: null, is cross-origin: false, is allowed by policy: true +PASS Policy to use: null, is cross-origin: true, is allowed by policy: false +PASS Policy to use: digital-credentials-get, is cross-origin: false, is allowed by policy: true +PASS Policy to use: digital-credentials-get, is cross-origin: true, is allowed by policy: true +PASS Policy to use: digital-credentials-get *, is cross-origin: true, is allowed by policy: true +PASS Policy to use: digital-credentials-get *, is cross-origin: false, is allowed by policy: true +PASS Policy to use: digital-credentials-get 'none', is cross-origin: true, is allowed by policy: false +PASS Policy to use: digital-credentials-get 'none', is cross-origin: false, is allowed by policy: false +PASS Policy to use: digital-credentials-get 'self', is cross-origin: true, is allowed by policy: false +PASS Policy to use: digital-credentials-get 'self', is cross-origin: false, is allowed by policy: true +PASS Policy to use: digital-credentials-get https://127.0.0.1:9443, is cross-origin: true, is allowed by policy: true +PASS Policy to use: digital-credentials-get https://127.0.0.1:9443, is cross-origin: false, is allowed by policy: false + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html new file mode 100644 index 0000000000000..f84495cd2c389 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html @@ -0,0 +1,124 @@ + + + + + Test allow attribute with "digital-credentials-get" and + CredentialsContainer's .get() method + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..4eb103f9c0c3f --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt @@ -0,0 +1,3 @@ + +PASS Permissions-Policy is by default 'self'. + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..34a40bdcfe746 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..c9abd2a0657ad --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt @@ -0,0 +1,5 @@ + + +FAIL Permissions-Policy header digital-credentials-get=() disallows the top-level document. promise_rejects_dom: function "function() { throw e }" threw object "TypeError: At least one provider must be specified." that is not a DOMException NotAllowedError: property "code" is equal to undefined, expected 0 +FAIL Permissions-Policy header digital-credentials-get=() disallows same-origin iframes. assert_false: Digital Credential API expected false got true + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..65b58066349da --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..02a76b7c3f289 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=() diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..2a904d018e058 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt @@ -0,0 +1,6 @@ + +PASS Permissions-Policy header digital-credentials-get=(self) allows the top-level document. +PASS Permissions-Policy header digital-credentials-get=(self) allows same-origin iframes. +PASS Permissions-Policy header digital-credentials-get=(self) disallows cross-origin iframes. +PASS Permissions-Policy header digital-credentials-get=(self) gets overridden by allow attribute. + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..019be25fa2d90 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html @@ -0,0 +1,59 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..1207d9e29a111 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=(self) diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..889badd382c60 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt @@ -0,0 +1,5 @@ + + +PASS Header-set policy is overridden in cross-origin iframe using allow attribute. +FAIL Setting digital-credentials-get=(self) disallows the API in same-origin iframes. assert_false: Digital Credential API expected false got true + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..393949f4116d2 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html @@ -0,0 +1,39 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..02a76b7c3f289 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=() diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/iframe.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/iframe.html new file mode 100644 index 0000000000000..b9f951537b8a0 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/iframe.html @@ -0,0 +1,69 @@ + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html new file mode 100644 index 0000000000000..4b212756c2291 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html @@ -0,0 +1,33 @@ + + + + + + + +

Digital Credentials iframe

+ diff --git a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js index d700cb086b362..cfc6d3caab103 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js +++ b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js @@ -30,7 +30,7 @@ function assert_permissions_policy_supported() { // promise. Used by test_feature_availability_with_post_message_result() function test_feature_availability( feature_descriptionOrObject, test, src, expect_feature_available, feature_name, - allowfullscreen, is_promise_test = false) { + allowfullscreen, is_promise_test = false, needs_focus = false) { if (feature_descriptionOrObject && feature_descriptionOrObject instanceof Object) { const { @@ -41,6 +41,7 @@ function test_feature_availability( feature_name, allowfullscreen, is_promise_test, + needs_focus, } = feature_descriptionOrObject; return test_feature_availability( feature_description, @@ -49,7 +50,8 @@ function test_feature_availability( expect_feature_available, feature_name, allowfullscreen, - is_promise_test + is_promise_test, + needs_focus, ); } @@ -84,6 +86,9 @@ function test_feature_availability( window.addEventListener('message', resolve); }).then(expectFeatureAvailable); document.body.appendChild(frame); + if (needs_focus) { + frame.focus(); + } return promise; } diff --git a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp index fd61ff72fc4f8..d4ae293b26dd5 100644 --- a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp +++ b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp @@ -51,6 +51,12 @@ void IdentityCredentialsContainer::get(CredentialRequestOptions&& options, Crede return; RefPtr document = this->document(); + ASSERT(document); + if (!PermissionsPolicy::isFeatureEnabled(PermissionsPolicy::Feature::DigitalCredentialsGetRule, *document, PermissionsPolicy::ShouldReportViolation::No)) { + promise.reject(Exception { ExceptionCode::NotAllowedError, "Third-party iframes are not allowed to call .get() unless explicitly allowed via Permissions Policy (digital-credentials-get)"_s }); + return; + } + if (!document->hasFocus()) { promise.reject(Exception { ExceptionCode::NotAllowedError, "The document is not focused."_s }); return; diff --git a/Source/WebCore/html/PermissionsPolicy.cpp b/Source/WebCore/html/PermissionsPolicy.cpp index 0d10bb914d774..ce3c0f64120e7 100644 --- a/Source/WebCore/html/PermissionsPolicy.cpp +++ b/Source/WebCore/html/PermissionsPolicy.cpp @@ -77,6 +77,8 @@ static ASCIILiteral toFeatureNameForLogging(PermissionsPolicy::Feature feature) #if ENABLE(WEB_AUTHN) case PermissionsPolicy::Feature::PublickeyCredentialsGetRule: return "PublickeyCredentialsGet"_s; + case PermissionsPolicy::Feature::DigitalCredentialsGetRule: + return "DigitalCredentialsGet"_s; #endif #if ENABLE(WEBXR) case PermissionsPolicy::Feature::XRSpatialTracking: @@ -117,6 +119,7 @@ static std::pair readFeatureIdentifier(S #endif #if ENABLE(WEB_AUTHN) constexpr auto publickeyCredentialsGetRuleToken { "publickey-credentials-get"_s }; + constexpr auto digitalCredentialsGetRuleToken { "digital-credentials-get"_s }; #endif #if ENABLE(WEBXR) constexpr auto xrSpatialTrackingToken { "xr-spatial-tracking"_s }; @@ -171,6 +174,9 @@ static std::pair readFeatureIdentifier(S } else if (value.startsWith(publickeyCredentialsGetRuleToken)) { feature = PermissionsPolicy::Feature::PublickeyCredentialsGetRule; remainingValue = value.substring(publickeyCredentialsGetRuleToken.length()); + } else if (value.startsWith(digitalCredentialsGetRuleToken)) { + feature = PermissionsPolicy::Feature::DigitalCredentialsGetRule; + remainingValue = value.substring(digitalCredentialsGetRuleToken.length()); #endif #if ENABLE(WEBXR) } else if (value.startsWith(xrSpatialTrackingToken)) { @@ -213,6 +219,7 @@ static ASCIILiteral defaultAllowlistValue(PermissionsPolicy::Feature feature) #endif #if ENABLE(WEB_AUTHN) case PermissionsPolicy::Feature::PublickeyCredentialsGetRule: + case PermissionsPolicy::Feature::DigitalCredentialsGetRule: #endif #if ENABLE(WEBXR) case PermissionsPolicy::Feature::XRSpatialTracking: diff --git a/Source/WebCore/html/PermissionsPolicy.h b/Source/WebCore/html/PermissionsPolicy.h index 331340b332068..577f8a2270878 100644 --- a/Source/WebCore/html/PermissionsPolicy.h +++ b/Source/WebCore/html/PermissionsPolicy.h @@ -63,6 +63,7 @@ class PermissionsPolicy { #endif #if ENABLE(WEB_AUTHN) PublickeyCredentialsGetRule, + DigitalCredentialsGetRule, #endif #if ENABLE(WEBXR) XRSpatialTracking, diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in index 2553619355c0b..54bfa4555c6dd 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in @@ -8320,6 +8320,7 @@ struct WebCore::OwnerPermissionsPolicyData { #endif #if ENABLE(WEB_AUTHN) PublickeyCredentialsGetRule, + DigitalCredentialsGetRule, #endif #if ENABLE(WEBXR) XRSpatialTracking,