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

Third Party cookies access in iframe #409

Open
jaissam10 opened this issue Aug 23, 2024 · 14 comments
Open

Third Party cookies access in iframe #409

jaissam10 opened this issue Aug 23, 2024 · 14 comments
Labels
third-party-cookies Third-party cookies

Comments

@jaissam10
Copy link

We have an extension that, when a PDF URL is loaded, inserts an iframe containing our web-accessible resource (an extension HTML page). This page then creates another iframe that loads our React application hosted on a domain, such as https://abc.com/index.html.

When a user opens a PDF URL, like https://pdfobject.com/pdf/sample.pdf, two iframes are embedded in the page—the first being our extension page and the second being our React application. These two iframes communicate with each other via postMessage.

The login process in our React application relies on cookies that are set on a different domain (e.g., subdomain.abc.com). However, these cookies are not being included in the network API call for sign-in when third-party cookies are disabled by the user or when the browser enforces third-party cookie restrictions.

Given that PDF URLs are dynamic, partitioned cookies (which are tied to the top-level site) aren't a viable solution.

How can we resolve this issue?

CC: @krgovind @samdutton

@jaissam10 jaissam10 added the third-party-cookies Third-party cookies label Aug 23, 2024
@cfredric
Copy link

Hi @jaissam10,

I'm not sure I fully understand your scenario, but the general solution when partitioned cookies/storage are not an option is to use unpartitioned storage, e.g. unpartitioned cookies. Your React app can use the Storage Access API to request access to that data.

@jaissam10
Copy link
Author

@cfredric Thanks for reaching out!

We’re unable to use the Document.requestStorageAccess() method because it prompts the user with a popup to allow or deny access. Since our URLs are dynamic for each PDF, this would trigger a popup every time, which isn’t a practical solution.

To explain further: If I open a PDF, like https://pdfobject.com/pdf/sample.pdf, the top-level site (PDF URL) is dynamic. We then insert our iframe (web_accessible_resource), i.e., (chrome-extension://id/viewer.html). Inside this, we load a nested iframe URL of CDN. So, there will be two nested iframes—one for chrome-extension://<id>/index.html and another for https://abc.com/index.html. (this is our hosted cdn)

Reference image:
image

@cfredric
Copy link

cfredric commented Sep 5, 2024

Since our URLs are dynamic for each PDF, this would trigger a popup every time, which isn’t a practical solution.

If I understand correctly, your CDN (https://abc.com) needs to access its unpartitioned data when embedded under some aribitrary set of top-level sites, correct? The problem is, that looks an awful lot like tracking. So the prompts are working as intended here.


However, there may still be options for you, since your app isn't just a CDN, it's also an extension. You can therefore use all of the extension APIs (e.g. chrome.cookies) to access the browser's cookies (provided you've requested the appropriate host permissions), and use message passing to send that info from your extension to the CDN iframe. Your CDN can then do whatever it needs to with those cookies, including setting partitioned cookies.

That approach is a bit more cumbersome than accessing the CDN's unpartitioned cookies directly, but as I said above, the unpartitioned cookies are intentionally inaccessible to the CDN unless the user grants permission, via the requestStorageAccess prompt or similar (soon). So, you'll have to use your extension's elevated privileges in order to get access.

@jaissam10
Copy link
Author

@cfredric Thanks for taking the time to check and follow up on this.

You're correct that our CDN (https://abc.com) needs access to unpartitioned data (cookies, storage, indexDB, cache, service worker). Additionally, when multiple PDFs are opened, the CDN's storage data should remain consistent across all tabs, which is only possible with unpartitioned storage or by ensuring it behaves that way.

Thanks, I believe the cookies issue can be resolved using chrome.cookies. For the storage issue, I’m considering using message passing between the CDN and chrome-extension://<id>/index.html, storing data in the extension’s storage, and then returning it via message passing when the PDF opens (i.e., when the CDN initializes).

However, could you help with addressing the service worker issue? Our CDN relies on a service worker that uses both cache and IndexedDB, which are currently partitioned. Do you have any suggestions on how we might solve this?

@cfredric
Copy link

cfredric commented Sep 5, 2024

However, could you help with addressing the service worker issue? Our CDN relies on a service worker that uses both cache and IndexedDB, which are currently partitioned. Do you have any suggestions on how we might solve this?

I'm not an expert on extensions, but are the options presented here viable for you? https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/lifecycle#persist-data

@jaissam10
Copy link
Author

@cfredric I don’t think this approach will be effective, especially regarding service workers (which rely on caching via CacheStorage and IndexedDB).

I’m currently using the CacheStorage APIs, but since they are now partitioned, I’m looking for a way to move this functionality to the extension or web-accessible resources to ensure unpartitioned access. Can you assist with this, or suggest an alternative solution?

@cfredric
Copy link

cfredric commented Sep 5, 2024

If I understand correctly, your chrome-extension:// iframe will be unpartitioned if your extension has host permissions for the top-level site that the iframe is embedded under. You can do that in two ways:

  1. Using the chrome.permissions API to request the permission at runtime, on demand.
  2. Using the <all_urls> pattern to preemptively request host permissions for all possible sites.

Note that requesting host permissions also comes with a prompt with warnings that users have to accept/deny when your extension is installed/updated. Host permissions are very powerful (as you can see), so this prompt is also working as intended IMO.

With that in mind, I would consider whether your extension actually needs unpartitioned storage, or whether it can work using partitioned storage instead. Then you could avoid prompting users and avoid needing the powerful permissions.

@jaissam10
Copy link
Author

@cfredric My chrome-extension:// iframe remains unpartitioned, regardless of the top-level site, which is why I’m considering moving the logic and storage functionalities there. However, I’m unsure how to transition the service worker functionality to this iframe. Since service workers can only intercept requests from the same origin where they are registered, moving it to the chrome-extension:// iframe means it won’t intercept and cache APIs from my CDN, which is happening currently. Could you provide guidance on how to manage this or suggest a different approach?

@cfredric
Copy link

cfredric commented Sep 5, 2024

Intercepting network requests from other origins sounds like a job for chrome.declarativeNetRequest or chrome.webRequest.

@jaissam10
Copy link
Author

@cfredric A service worker has a fetch event listener (self.addEventListener("fetch", () => {})) that is triggered for API calls within the scope defined during its registration. This allows us to implement custom logic, such as checking if a request is already cached, returning the cached response if available, or making a network request and then caching the response for future use.

This behavior is not achievable with Declarative Net Request (DNR), as DNR operates more at the network level for intercepting, blocking, or modifying requests, but lacks the same flexibility for managing and serving cached responses dynamically.

Let me know if I am wrong somewhere.

@jaissam10
Copy link
Author

@cfredric @krgovind @samdutton @ilipkind Could any of you assist with this? I would greatly appreciate your feedback.

@cfredric
Copy link

cfredric commented Sep 9, 2024

If I understand correctly, you're asking how to use an unpartitioned service worker to intercept network requests for some origin (https://abc.com) while it's in a partitioned context.

Web platform

Web Platform APIs (on their own) definitely do not provide the ability to intercept another origin's network requests, since doing so would violate the Same Origin Policy. So any solution that bypasses the SOP would necessarily be in the extension APIs.

With that framing, we can consider alternatives that don't violate the SOP; i.e., things that your CDN can do on its own origin. The ideal answer would be to let the CDN access an unpartitioned service worker via the Storage Access API, but unpartitioned service workers are intentionally inaccessible in third-party contexts, due to security concerns. So this functionality is intentionally not possible via Web Platform APIs.

Extensions

I'm not aware of a way to do this via extension APIs. chrome.declarativeNetRequest or chrome.webRequest are the APIs that extensions can use to observe, modify, and block outgoing network requests, but I agree, those APIs don't appear to support caching -- but I am not an extensions expert.

You can consider filing a feature request for this.

@jaissam10
Copy link
Author

jaissam10 commented Oct 9, 2024

@cfredric I have raised the issue here: w3c/webextensions#708.

I also discovered that the HTTP cache is partitioned, resulting in actual network requests for multiple XHR calls from our CDN (which we want to cache) each time a new PDF is opened on a different domain, instead of returning from the HTTP cache (disk/memory).

Could you suggest a way to make the HTTP cache unpartitioned or provide any workaround to resolve this issue?

Note: I observed something strange—some requests for the second PDF are being served from the memory cache. I'm not sure why that's happening.

@cfredric
Copy link

Could you suggest a way to make the HTTP cache unpartitioned or provide any workaround to resolve this issue?

I'm not aware that there is a workaround. This is a feature that shipped in all major browsers years ago, to improve security and privacy. I'd consider it a bug in Chrome if it were possible to bypass it on the web at large.

Chrome's proposal had some discussion on performance and those engineers found the impact to be largely negligible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
third-party-cookies Third-party cookies
Projects
None yet
Development

No branches or pull requests

2 participants