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

Inconsistent request storage Access behavior #4

Closed
jagadeeshaby opened this issue Aug 1, 2023 · 9 comments
Closed

Inconsistent request storage Access behavior #4

jagadeeshaby opened this issue Aug 1, 2023 · 9 comments

Comments

@jagadeeshaby
Copy link

While testing the RSA implementation we found that in few cases permissions.query would result in Prompt output, however document.hasStorageAccess() results in true. Not sure what's causing it though.

await navigator.permissions.query({
        name: "storage-access",
      });

Are there any known bugs/issues among hasStorageAccess v/s navigator.permissions.query?

Also another scenario observed is, even after making an explicit rsa call, the permissions goes into denied mode (DOMException: requestStorageAccess not allowed) , not sure how to get this working again. We are using an explicit button click action to request the permission. Tried clearing the site data and other info nothing worked.

@cfredric
Copy link
Owner

cfredric commented Aug 1, 2023

Hi @jagadeeshaby, thanks for testing this out!

Are there any known bugs/issues among hasStorageAccess v/s navigator.permissions.query?

Without more information about the cases you've found, it's hard to say whether it's a bug or not, but there are some cases when navigator.permissions.query({name: "storage-access"}) and document.hasStorageAccess() are allowed to differ. In particular:

  • If the caller of document.hasStorageAccess() is the top-level document, then the specification currently says that document.hasStorageAccess() should return true (regardless of whether a permission grant actually exists and would be found by navigator.permissions.query).
  • If the top-level site and embedded site are the "same authority", then the specification currently says that document.hasStorageAccess() should return true (regardless of whether a permission grant actually exists). Currently, the definition of "same authority" is a little fuzzy, but it roughly means that the two documents are from the same site and there's no cross-site intermediate iframe between them.

If you are testing in Chrome Canary, you may also be seeing some new work done by one of my colleagues. There is a proposed change to the specification such that document.hasStorageAccess() takes the user's cookie settings into account. This change hasn't landed in the specification yet, but has landed in Chrome Canary (M117). A similar change will come soon to update document.requestStorageAccess() so that it resolves (without creating a prompt) if the user's cookie settings already allow unpartitioned cookie access. These changes will ideally make it so that web developers can just call document.hasStorageAccess() and document.requestStorageAccess(), and know that when those methods resolve and/or return true, that means they really do have access to unpartitioned cookies. (The permission state itself can still be checked via navigator.permissions.query.)

Also another scenario observed is, even after making an explicit rsa call, the permissions goes into denied mode (DOMException: requestStorageAccess not allowed) , not sure how to get this working again.

Can you give any more information about the behavior you're seeing, and how to reproduce this? In particular:

  • What version of Chrome are you using? (See chrome://version.)
  • What Chrome flags are enabled? (See chrome://flags.)
  • What command-line flags did you use to start Chrome?
  • What output is printed in the devtools console after you reproduce this behavior? (Whenever the document.requestStorageAccess promise is rejected, the devtools console should have more information about why it was rejected.)
  • Does the browser create a prompt? If so, do you ignore, dismiss (click the X in the corner), or deny the prompt?

I'm not aware of any bugs in the API at the moment, but am happy to debug this with you.

CC @shuranhuang

@andywang219
Copy link

andywang219 commented Aug 2, 2023

Hi @cfredric, I have a similar question. I've been testing on Chrome Version 115.0.5790.114 and my set up is the following:

  • I am embedding a site within an iframe in another top-level site
  • The embedded site calls await document.requestStorageAccess().then(successCallback, failureCallback)
  • I click "block" in Chrome's prompt

Flags I'm using:

  • Storage Access API
  • Storage Access API permission UI

I realized that even though I clicked "block" in the Chrome prompt, the subsequent await navigator.permissions.query({ name: "storage-access", }); call will still return "prompt". I would expect this to return "denied". Is this result expected?

@cfredric
Copy link
Owner

cfredric commented Aug 2, 2023

Hi @andywang219, yes, that is the expected result. Please see the specification here, particularly the note under the "permission query algorithm":

NOTE: The "denied" permission state is not revealed to avoid exposing the user’s decision to developers. This is done to prevent retaliation against the user and repeated prompting to the detriment of the user experience.

You (the user) should still be able to see the "blocked" status in the permissions UI on chrome://settings/content/storageAccess.

@andywang219
Copy link

Thank you!

@jagadeeshaby
Copy link
Author

jagadeeshaby commented Aug 11, 2023

I'm struggling with testing the API end to end: Here is what i observe on chrome canary so far.

Example setup is as follows:

  • www.locks.com is the customer site who is embedding the SASS app (localhost) using the JS library.
  • JS library first simply redirect the user to /request-storage-access page within SASS app
  • /request-storage-access page validates whether hasStorageAccess is true , if not then shows the request access screen where customer clicks on a button which in turn redirects the localhost sass app.
  • SASS app uses popups to set login cookies and those cookies will be used for further login flow.

and browser setting is as follows: 2 flags tied to storage partition is on (prompt and UI)

Scenario 1:

  • First time customer trying to access their website which embeds the SASS app (localhost), SASS app finds no access to storage (cookies), and show the Action required screen with grant access button
  • by clicking on grant access - browser prompts with allow/block button
  • clicking on allow resolve the promise and grants access and signals for SASS app redirections and SASS app try to load it's content and fails as it doesn't have access to cookies
  • SASS embedded site XML HTTP requests shows "cookie was blocked due to user preferences" on the both the cookies set by the login POPUP and doesn't give access to cookies set on localhost within www.locks.com.

Scenario 2

if i would go ahead and explicitly allow access to third party cookies by clicking on "site not working" prompt on the URL bar then everything works this time, this is same as allowing third party cookies so i don't think i should be doing this

So i'm stuck on identifying what should be the default cookie settings within privacy and security for testing, at present i have like below and with this i couldn't get the request storage access working for me.


Block third-party cookies

Sites can use cookies to improve your browsing experience, for example, to keep you signed in or to remember items in your shopping cart

Sites can't use your cookies to see your browsing activity across different sites, for example, to personalize ads. Features on some sites may not work.

Could you clarify around what should be the default cookie settings when chrome releases request storage feature and after third party cookie deprecation, and is it expected to have the "Block third-party cookies" settings enabled and then make use of RSA query to gain access to those cookies, if yes do you do know why isn't it not working?

Also while testing locally does localhost endpoint makes any difference for this behavior?

@cfredric
Copy link
Owner

Hi @jagadeeshaby - thanks for continuing to test this out.

and browser setting is as follows: 2 flags tied to storage partition is on (prompt and UI)

Just to confirm - are you referring to the #third-party-storage-partitioning flag? Please be aware that that flag is not related to the Storage Access API, and you also have to set the #storage-access-api flag to "Enabled (with prompt)" (though it sounds like you've done that).

Scenario 1:

If I understand correctly, you're requesting storage access from one embedded page, which then redirects to a different page (that tries to actually use the storage access)? The reason I ask is that by default*, every frame that wants access to unpartitioned cookies must ask for it, even if some other frame has already requested and obtained the same access. I.e., the embedded SaaS app needs to call document.requestStorageAccess() before it is allowed to use the permission that was granted by some other frame (or a previous visit). This is for security reasons; please see privacycg/storage-access#113 for motivation and privacycg/storage-access#141 (especially the web-platform tests in https://crrev.com/c/4117243) for technical details/expected behavior.

*With that said, there are some situations in which a frame that obtains storage access and then navigates somewhere else is allowed to keep the storage access, without having to call document.requestStorageAccess() again first. With that in mind:

  • Which frame initiates the redirect in your scenario? Is it the frame that requested storage access, or something else? (In order to keep storage access, the navigation must be initiated by the target of the navigation, i.e. the frame must navigate itself.)
  • Are all the origins in the redirect chain same-origin? Or is there a cross-origin redirect (e.g. https://localhost:8888/ -> https://localhost:9999/, or https://www.saas.com/ -> https://sub.sass.com/)? (In order to keep storage access, there must be no cross-origin redirects in the redirect chain.)

Could you clarify around what should be the default cookie settings when chrome releases request storage feature and after third party cookie deprecation, and is it expected to have the "Block third-party cookies" settings enabled and then make use of RSA query to gain access to those cookies, if yes do you do know why isn't it not working?

Confirmed that blocking third-party cookies and then using document.requestStorageAccess to gain access to them for your app is expected to work, so I think your settings are fine. I think something else in the scenario is making the storage-access permission inapplicable.

Also while testing locally does localhost endpoint makes any difference for this behavior?

I'm not aware of anything that would cause an issue when using localhost. As long as you're able to call document.requestStorageAccess() and get it to resolve, and you can set cookies on localhost, I would expect the scenario to work (assuming everything else is set up properly).

@jagadeeshaby
Copy link
Author

Confirmed that blocking third-party cookies and then using document.requestStorageAccess to gain access to them for your app is expected to work, so I think your settings are fine.

thank you, that makes complete sense to me

I think something else in the scenario is making the storage-access permission inapplicable.

this is where i'm struggling , below is the code snippet used for testing, where i start with hasStorageAccess method and then invoke requestStorageAccess once and show the access button if no access and then proceed with click action. This code is executes within the embedded rsa page.

   /**
     * method which checks for storage access and returns whether the permission is granted or not
     * This method is called twice one without user interactions (in few cases we found success calling this method which immediately resolves to be granted where hasStorageAccess method is ineffective to do so) 
     * and another with explicit grant access button from request access view 
     */
    const requestStorageAccess  = () =>  {
        document.requestStorageAccess().then(
            () => {
                console.log("granted");
                granted();
            },
            (err, ...rest) => {
                // Handle errors
                let { name, message } = err;
                console.log(name, message);

                if(isRequestAccessViewVisible){
                    ViewHandler.renderAccessDeniedView();
                    deny();
                }else{
                    ViewHandler.renderRequestAccessView(requestStorageAccess);
                    isRequestAccessViewVisible = true;
                }
            }
        );
    }

    /**
     * Method which looks for the internal cookie access test result and also  hasStorageAccess result and send INIT event back to the calee. 
     * hasCookieAccess - simply creates new cookie and check if that's accessible 
     */
     const hasStorageAccess = async () =>  {
        let hasAccess = await document.hasStorageAccess();
        console.log("document.hasStorageAccess()", hasAccess);
        var access = CookieHandler.hasCookieAccess() || hasAccess;
        if (access) {
            granted();
        } else {
            requestStorageAccess();
        }
    }

If I understand correctly, you're requesting storage access from one embedded page, which then redirects to a different page (that tries to actually use the storage access)?

No, it's like first get access, and then open login popup which runs on the same domain as the embedded page which sets the cookie and auto close. and embedded page is the one which uses those cookies set in the popup. note cookie is set using the same domain which gets embedded as well ( same site)

I would expect that once rsa is granted within the embedded context , cookies set on the embedded domain should be made available, but it doesn't work.

@jagadeeshaby
Copy link
Author

Okay here is what i found, seems like the implementation with storage APIs works perfectly fine as soon as move to https enabled endpoint ( spec says the same as well) . I had to test this out on our Integ environment and everything works just fine.

May be it's worth highlighting that for local testing make sure to have https enabled.

@cfredric
Copy link
Owner

seems like the implementation with storage APIs works perfectly fine as soon as move to https enabled endpoint

Great, glad to hear that!

I've added a note about the security requirements to the testing instructions section (49ed2b8).

Since it sounds like you've found the source of the problem, I'm going to close this issue.

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

No branches or pull requests

3 participants