privacysandbox / privacy-sandbox-dev-support

Discuss your Privacy Sandbox developer questions with the Chrome team.
Apache License 2.0
180 stars 74 forks source link

DOMException Permission to join interest group denied #64

Closed TheTamFamily closed 1 year ago

TheTamFamily commented 1 year ago

Hi,

I'm looking for some guidance. In the TURTLEDOVE FLEDGE Explainer, it is possible to delegate the owner of an Interest Group to another party that this is NOT the origin domain. In the Delegate Permissions section of the Explainer it says:

When a frame navigated to one domain calls joinAdInterestGroup() or leaveAdInterestGroup() for an interest group with a different owner, the browser will fetch the URL https://owner.domain/.well-known/interest-group/permissions/?origin=frame.origin, where owner.domain is domain that owns the interest group and frame.origin is the origin of the frame.

My questions are:

  1. Should the .well-known file be placed in the directory https://owner.domain/.well-known/interest-group/permissions
  2. Should the file have any extension or is simply named .well-known
  3. Do you have an example of a .well-known file that allows joinAdInterestGroup and leaveAdInterestGroup

Thank you

TheTamFamily commented 1 year ago

In the FOT for FLEDGE I see that the .well-known URL is not yet supported.

The documentation suggests setting in the Response Header from the cross origin site:

X-Allow-FLEDGE = true

Besides this Header what other security headers are required as I am still getting:

Uncaught (in promise) DOMException: Permission to join interest group denied

When I tried to create an interest group in another domain. For example:

  1. I visited a.com on my browser.
  2. I open Dev Console in Chrome.
  3. I create an interest group using javascript at the top level in domain b.com.

Then I get the error.

maudnals commented 1 year ago

Thanks for your question! @kevinkiklee / @samdutton who will likely have information / troubleshooting tips to share.

kevinkiklee commented 1 year ago

Regarding the .well-known path, it should not be a file, but it should be a server that responds to https://owner.domain/ that receives a request at /.well-known/interest-group/permissions/ path. The server should parse the query param ?origin=frame.origin and return a JSON response in the following format containing what action is allowed for that frame.origin:

{ 
  "joinAdInterestGroup": true/false,
  "leaveAdInterestGroup": true/false
}
dmdabbs commented 1 year ago

Can one enable the well-known permission checking using a feature flag?

kevinkiklee commented 1 year ago

Regarding the Uncaught (in promise) DOMException: Permission to join interest group denied error message you are receiving, I would like more information. Other than the X-Allow-FLEDGE response header, there shouldn't be other gating mechanisms.

Would you be able to check if you can run the demo? Visit the advertiser page then visit the publisher page. Do you see a blue mock ad rendered on the publisher page?

If so, try the following steps:

  1. Visit the advertiser page
  2. Open up DevTools
  3. Go to the 'Applications' tab and open 'Storage' -> 'Interest groups' in the sidebar
  4. Also open the console alongside the application tab by pressing 'escape'
  5. In the console, select the https://fledge-demo-dsp.web.app context image
  6. Executing the following code in the console:
    
    const interestGroup = {
    owner: `https://fledge-demo-dsp.web.app`,
    name: 'test',
    };

navigator.joinAdInterestGroup(interestGroup, 1000)


7. Check if the interest group has been added in the 'Applications' tab view

If you do see an interest group being added, then would you be able to compare your interest group code with the one in the demo?  Let me know if there are any differences you can spot: [join-ad-interest-group.js](https://github.com/GoogleChromeLabs/fledge-demo/blob/main/sites/dsp/join-ad-interest-group.js).  Also, if it still doesn't work, would you be able to share your interest group code?  
kevinkiklee commented 1 year ago

Can one enable the well-known permission checking using a feature flag?

@dmdabbs Turns out the feature has been implemented already and is testable right now without a feature flag. If the interest group owner origin is different from the origin of the frame that initiates the call, a request will be sent to that interest group owner's origin at https://[[IG_OWNER_ORIGIN]]/.well-known/interest-group/permissions/?origin=[[FRAME_ORIGIN]].

TheTamFamily commented 1 year ago

To Kevin,

Using your demo as guidance I managed to create the Interest Group and delegate the ownership to a 3rd party. It seemed I have to create the Interest Group within an iFrame for this to work.

The flow is as follows:

  1. Run this: (function() { _st.inject.iframe("https://thetamster.com/fledge-tag.html"); })();
  2. fledge-tag.html contains:

I will test the well-known permission.

Thanks,

David

dmdabbs commented 1 year ago

Thank you @kevinkiklee.

The explainer states

The site can allow or deny permission to any or all third parties via a Permissions-Policy (directive named "join-ad-interest-group"), where the default policy is to allow all in the top-level page and to deny all in cross-domain iframes.

Can you confirm that the following would have to be in place for a site wishing to permit particular partners' embedded frames to call the interest group APIs:

  1. Site would supply a Permissions Policy header. e.g. Permissions-Policy: join-ad-interest-group=("https://fledge.partner1.com" "https://tdove.partner2.com")

  2. And the two partners' well-known endpoint would need to respond in the affirmative for the hosting site's origin embedding the partner's frame.

TheTamFamily commented 1 year ago

Reopen ticket and await Kevin's response to dmdabbs comment above.

I'm also interested to know if FLEDGE supports the Permissions Policy Header and whether there is any documentation that you can point to on how this would be set. For example, is this set in the Response Header.

kevinkiklee commented 1 year ago

@dmdabbs

  1. Yes, that is the correct way to set the permissions policy response headers. Note that for experimentation, the default permission allows all origins, so the permissions policy headers are not needed right now. In the future, it will be disabled by default and you will have to explicitly allow them in the header. We will provide substantial notice before we update the default settings.
  2. Yes, that is correct.

@TheTamFamily In the response header of the page that gets returned from the server, you can control which origins in the page have access to which browser features. You can learn more about Permissions Policy from the blog explainer.

FLEDGE can use permissions policy from the buyer side with join-ad-interest-group and the seller side with run-ad-auction feature names.

utes12 commented 1 year ago

@kevinkiklee, your walkthrough as described in https://github.com/GoogleChromeLabs/privacy-sandbox-dev-support/issues/64#issuecomment-1306117367 make sense and works. However, it still does not seem to represent the the .well-known lookup scenario as there is no calls to the .well-known endpoint.

Broken test scenario:

  1. Visit the advertiser page
  2. Open up DevTools
  3. Go to the 'Applications' tab and open 'Storage' -> 'Interest groups' in the sidebar
  4. Also open the console alongside the application tab by pressing 'escape'
  5. ~In the console, select the https://fledge-demo-dsp.web.app context~ - We want the call to come from a different origin, so we will skip this step
  6. Executing the following code in the console:
const interestGroup = {
  owner: `https://fledge-demo-dsp.web.app`,
  name: 'test',
};

navigator.joinAdInterestGroup(interestGroup, 1000)
  1. We now see a call to check permissions (not occurring before): https://fledge-demo-dsp.web.app/.well-known/interest-group/permissions/?origin=https%3A%2F%2Ffledge-demo-advertiser.web.app

The .well-known response has been mocked using Charles Proxy

:status: 200
content-length: 66
content-type: application/json
x-allow-fledge: true

{
  "joinAdInterestGroup": true,
  "leaveAdInterestGroup": true
}
  1. Creation fails with "Uncaught (in promise) DOMException: Permission to join interest group denied."

Questions:

  1. Is this an incorrect understanding of how to use the .well-known setup, as the proper permissions are being returned?
  2. Should the call joinAdInterestGroup call always come from an iframe owned by the origin in the IG?
TheTamFamily commented 1 year ago

Coming back to this issue.

I have two sites: https://thetamster.com (advertiser) http://exploreflegde.com (interest group owner)

On the advertiser site I eexecute the following HTML in an iframe:

`

`

I call this function in the Chrome console:

(function(){ var ifrm = document.createElement("iframe"); ifrm.setAttribute("src", "fledge-tag-explorefledge.html"); ifrm.style.width = "640px"; ifrm.style.height = "480px"; document.body.appendChild(ifrm); }) ();

On the interest group owner site I set up an endpoint that returns a json.

Endpoint = https://explorefledge.com/.well-known/interest-group/permissions/?origin=https://thetamster.com json = { "joinAdInterestGroup": "true", "leaveAdInterestGroup": "true"}

I also return the response headers:

Access-Control-Allow-Origin * X-Allow-FLEDGE true

I am still receiving the error below when trying to create the interest group oin site https://thetamster.com with interest group owner https://explorefledge.com

Uncaught (in promise) DOMException: Permission to join interest group denied.

dmdabbs commented 1 year ago

Hi @TheTamFamily . I get the same thing on my end due to your self-signed cert. I use Chrome Canary and despite the .well-known permission delegation fetch not showing in Network, it does share that there was an issue with the request: image

I get following error when loading that or any other explorefledge.com url:

SelfSignedCert (self signed certificate) Blocked by SSL_SELF_SIGNED The destination explorefledge.com is not reachable.

kevinkiklee commented 1 year ago

@TheTamFamily @dmdabbs Hello there. Sorry that this ticket got buried. We recently started finding tickets that fell through, and I actually just started working on this issue again.

I have tested it out, and I am also having trouble getting one origin to add a user to an interest group owned by another origin.

I have reached out to the eng team, and we are currently looking into the issue. No solution yet, but at least I wanted to let you all know that we are looking into it since this ticket has been opened for quite awhile. Also, again, apologize for this ticket slipping through the cracks.


I've added this use case to the demo for testing, and I can see it throwing the same error that @TheTamFamily saw.

Participants:

I have set up a case where the Adtech adds the user to an interest group owned by the DSP, and two iframes have been added on the advertiser page (https://fledge-demo-advertiser.web.app/):

image

User is added to an interest group owned by the DSP:

image

In this adtech code, it's trying to join the DSP's IG: https://github.com/GoogleChromeLabs/fledge-demo/blob/main/functions/view/adtech/index.hbs ({{{dspUrl}}} is a macro that gets replaced with the DSP origin)

And this is the DSP code that sends a JSON reponse for /.well-known/interest-group/permissions: https://github.com/GoogleChromeLabs/fledge-demo/blob/main/functions/app/dsp/index.js#L22. (You can see the actual response here: https://fledge-demo-dsp.web.app/.well-known/interest-group/permissions).

I am continuing to test, and as soon as we find a solution, I'll reply here right away.

dmdabbs commented 1 year ago

@kevinkiklee If you run net-log trace do you see anything interesting about the well-known fetch?

kevinkiklee commented 1 year ago

@dmdabbs No, I didn't find anything of significance when logging from the server.

Edit: Sorry, misunderstood your comment initially. Let me look at the netlog and see if anything comes up.

TheTamFamily commented 1 year ago

Hi @dmdabbs, @kevinkiklee,

I have fixed the SSL certificate on site https://explorefledge.com, though this was not the issue as to why I am seeing the DOMException error. I carried out some more tests and I did manage to create an interest group that is owned by a different domain. The issue was that the json response from the preflight cors request -

https://explorefledge.com/.well-known/interest-group/permissions/?origin=https://thetamster.com

was not correctly formatted.

  1. If you go to https://thetamster.com
  2. Open the Console.
  3. Run this code: (function(){ var ifrm = document.createElement("iframe"); ifrm.setAttribute("src", "fledge-tag-explorefledge.html"); ifrm.style.width = "640px"; ifrm.style.height = "480px"; document.body.appendChild(ifrm); }) ();

You will see the interest group "pets" created owned by "https://explorefledge.com".

Thanks for your help.

kevinkiklee commented 1 year ago

@TheTamFamily Yep, I learned yesterday from the eng team that the request is a CORS request, and I'm glad you were able to figure it out also!

Demo page: https://fledge-demo-advertiser.web.app/

image


Summary: when an iframe wants to use an interest group owned by another origin, the origin that owns the interest group responds with the permissions information as a JSON at the path /.well-known/interest-group/permissions. The request is a CORS request, so the server should be set up to respond to a CORS request.