Add experimental allowlisting API for websites
Background
We'd like to experiment with giving websites a way to ask users to allowlist them to provide a better user experience than we can currently offer via the extension's own UI. Since this is just an experiment at this point, the API should be restricted to trusted partners.
Sequence diagram (parts in red are not included in the internal prototype)
See also internal prototype development issue.
Use case
Providing an easier and more straight-forward way for users to allowlist websites of their choosing.
What to change
- Implement experimental allowlisting API for websites (see sequence diagram above).
- Unless page is already allowlisted, listen to "domain_allowlisting_request" event, containing the details:
-
string signature
RSASSA-PKCS1-v1_5 algorithm, SHA512 hash and 4096 bit-long modulus
signed data:${location.hostname},${timestamp}
-
number timestamp
timestamp of request creation in milliseconds
time must be in the past and not older than one hour
-
string signature
- Verify request data using keys provided by integrator.
incl. check whether event object has been tampered with, check timestamp, verify signature - If verified, ask integrator to allowlist the website.
- If successful, dispatch "domain_allowlisting_success" event.
- Unless page is already allowlisted, listen to "domain_allowlisting_request" event, containing the details:
- Provide way to set list of trusted partner keys for authorizing use of allowlisting API.
- Provide way to get notified of any failures in verifying allowlisting requests (e.g. invalid signature, invalid timestamp).
See also internal prototype implementation based on legacy adblockpluschrome codebase for more details. Note that includes a second verification for each key, but that workaround should be removed.
Additional requirements
- The experimental allowlisting API should only be usable by authorized partners, as indicated by their keys.
- The extension should not expose its presence to the website, except for dispatching the "domain_allowlisting_success" event after successfully verifying the allowlisting request (i.e. "domain_allowlisting_request" event).
- The attempted use/misuse of the allowlisting API by unauthorized parties (incl. DoS attacks) should not lead to performance or security problems.
- The time it takes from receiving the "domain_allowlisting_request" event to dispatching the "domain_allowlisting_request" event, should be kept at a minimum.
- The content script should not initiate the allowlisting directly, but instead leave it up to the background page to verify the request to determine whether the domain should be allowlisted.
- It is sufficient if only the domain of the top-level frame can be allowlisted. Therefore we may want to ignore allowlisting requests that originate from subframes under a different domain.
Proposed API additions
- EWE.allowlisting.setAllowlistingCallback(Function fn(URL.hostname domain) returns Promise)
- EWE.allowlisting.setAuthorizedKeys(string[] keys)
- EWE.allowlisting.onUnauthorized.addListener(Function fn(AuthorizationError error))
- AuthorizationError
-
string name
e.g. "invalid_timestamp" -
object request
request data that was provided to us by the website (e.g.{domain: ..., signature: ..., timestamp: ...}
)
-
string name
Example usage:
EWE.allowlisting.setAuthorizedKeys(["..."]);
EWE.allowlisting.setAllowlistingCallback(async (domain) =>
{
await EWE.filters.add([`@@||${domain}^$document`]);
});
EWE.allowlisting.onUnauthorized.addListener((error) =>
{
console.error(error);
});
Further information
- The reason why allowlisting filters need to be created by the integrator is to ensure that the behavior is consistent with allowlisting pages through other means, which can be different in each product.
- Due to this being an experimental feature, we should develop and review this feature in private and only make it public when it gets merged.