w3c / webextensions

Charter and administrivia for the WebExtensions Community Group (WECG)
Other
576 stars 50 forks source link

Manifest v3 problems: ability to update the set-cookie header in response headers and also set dynamic header values #626

Open vish30 opened 3 weeks ago

vish30 commented 3 weeks ago

There are two issues in manifest v3:

  1. Not being able to modify the "set-cookie" response header.
  2. Not being able to set dynamic (runtime) values for any response & request header synchronously (before they are consumed by the browser/application/server).

We have an extension wherein the users can have different login sessions in each tab. Here is my manifest v2 code:

  (details) => {
    const { tabId, responseHeaders } = details;
    responseHeaders.forEach((responseHeader) => {
      if (
        responseHeader.name.toLowerCase() === 'set-cookie'
      ) {
        responseHeader.value = `${tabId}_${responseHeader.value}`;
      }
    });
    return { responseHeaders };
  },
  { urls: allowedURLs },
  [
    'blocking',
    'responseHeaders',
    chrome.webRequest.OnBeforeSendHeadersOptions.EXTRA_HEADERS
  ].filter(Boolean)
);

I am not able to replicate this in manifest v3 as the webRequestBlocking permission is not available and the rules (dynamic/static) doesn't support adding dynamic/runtime value for any header. Also, updating the "set-cookie" header is also not allowed.

oliverdunk commented 3 weeks ago

In Chrome it is already possible to modify the set-cookie header:

{
  "id": 1,
  "priority": 1,
  "action": {
    "type": "modifyHeaders",
    "responseHeaders": [
      { "header": "set-cookie", "operation": "set", "value": "example=test" }
    ]
  }
}

I've put a full example here - note that due to this bug those changes aren't currently visible in the request tab of DevTools. However, visiting https://example.com and then checking the Cookies section in DevTools should show the cookie.

Setting dynamic values is a request we've heard in the past, but as you point out isn't currently possible.

Is the core feature of your extension providing the different sessions per tab or are you using that to solve another problem?

vish30 commented 3 weeks ago

@oliverdunk Thanks for the clarification on "set-cookie" header.

However, the second issue is critical for my extension to be migrated to V3. And, as you guessed correctly, the main intention of the extension is to provide multi-session support in the same window. For this, I am adding tabId as a prefix for the value of the "set-cookie" response header and request header, I am removing the prefix from the "Cookie" header.

Here is the v2 extension: Extension link

vish30 commented 2 weeks ago

@oliverdunk Can you please let us know if setting dynamic header values will be possible or not? If yes, an ETA will be really helpful. If no, we would be forced to shift to firefox.

oliverdunk commented 2 weeks ago

Hi @vish30, we don't have any changes on the roadmap which would make adding the tab ID possible from a static rule.

However, you can add session rules with a tabId condition (docs). Combined with some upcoming planned work to support RegEx matching and substitution for headers, I believe your use case should be solvable.

It would look something like this:

chrome.declarativeNetRequest.updateSessionRules({
  addRules: [{
    "id": 1,
    "action": {
      "type": chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
      "responseHeaders": [
        {
          "header": "Set-Cookie",
          "operation": chrome.declarativeNetRequest.HeaderOperation.SET,
          "regexFilter": ".*",
          "regexSubstitution": `${tabId}_\\1`
        }
      ]
    },
    "condition": { tabIds: [tabId] },
  }]
});

You would be able to call this each time a tab is created.

This is next up on our roadmap so will hopefully be available soon.

vish30 commented 4 days ago

Hi @oliverdunk, thanks for the update.

But, I doubt will this solution also work for removing the same prefix from the cookie header before sending a request from client to server?

Here is a sample implementation in v2:

chrome.webRequest.onBeforeSendHeaders.addListener(
  (details) => {
    const { tabId, requestHeaders, url } = details;
    requestHeaders.forEach((requestHeader) => {
      if (
        requestHeader.name.toLowerCase() === 'cookie'
      ) {
        requestHeader.value = fnToRemovePrefixFromCookies(
          requestHeader.value,
          tabId
        );
      }
    });
    return { requestHeaders };
  },
  { urls: allowedURLs },
  [
    'requestHeaders',
    chrome.webRequest.OnBeforeSendHeadersOptions.EXTRA_HEADERS
  ].filter(Boolean)
);
oliverdunk commented 3 days ago

But, I doubt will this solution also work for removing the same prefix from the cookie header before sending a request from client to server?

Could you share your fnToRemovePrefixFromCookies implementation? Assuming this can be expressed in the declarative syntax, we do plan to support RegEx matching on both request and response headers, so that should be possible.