Re: Storefront API Generation of delegate access token Shopify-Storefront-Private-Token

Solved

Storefront API Generation of delegate access token Shopify-Storefront-Private-Token

DrewGarratt
Shopify Partner
7 1 11

TLDR There is no documented method for the generation of delegate access tokens for use with the harder Shopify-Storefront-Private-Token

With the release of Hydrogen the Rate Limits section of the Storefront API has been updated with the following.

 

If you use a server-side library, the IP address of the request will be your server’s address. To ensure your app is throttled correctly, use a delegate access token and pass it in theShopify-Storefront-Private-Tokenheader from server contexts. Requests using this authentication method can pass the buyer IP into theShopify-Storefront-Buyer-IPheader.

As this new annotation makes clear, sending requests from a server without passing both the delegate access token and the buyer's IP address will result in requests quickly being throttled. This is crucial to both the development of Hydrogen storefronts and Headless applications with server-rendered components.

Currently, it appears that the documentation points developers to generate a delegate access token, however, these tokens are associated with the admin API and will return 403 responses if used as suggested above. My suspicion is that the Oxygen sales channel is able to generate these tokens in some currently undocumented/unimplemented way. In either case, documentation needs to be updated to reflect this.

Accepted Solution (1)
DrewGarratt
Shopify Partner
7 1 11

This is an accepted solution.

Hi _JCC_

Thanks for letting us know the new documentation is up. It looks as if this has been revised a little in the last day or so. But for those looking I've managed to successfully create a token!

What the documentation doesn't make clear is what has changed. It is now possible to create a delegate access token with various unauthenticated scopes. 

Below is the GraphQL admin API mutation required to create a delegate token with the correct access scopes to be used in the Shopify-Storefront-Private-Token header. The access scope list used is identical to that of a token created using the storefrontAccessTokenCreate mutation.

mutation {
  delegateAccessTokenCreate(input: { delegateAccessScope: [
    "unauthenticated_read_content",
    "unauthenticated_read_customer_tags",
    "unauthenticated_read_product_tags",
    "unauthenticated_read_product_inventory",
    "unauthenticated_read_product_listings",
    "unauthenticated_write_checkouts",
    "unauthenticated_read_checkouts",
    "unauthenticated_write_customers",
    "unauthenticated_read_customers",
    "unauthenticated_read_selling_plans",
    "unauthenticated_read_product_pickup_locations"
   ] 
  })
  {
    delegateAccessToken {
      accessToken
    }
    shop {
      id
    }
    userErrors {
      field
      message
    }
  }
}


It would be great if we could see the delegate access token documentation updated with a list of valid scope strings and perhaps even an example like the above 😊

View solution in original post

Replies 18 (18)

0xrandom
Visitor
2 0 2

Would also love if someone from the Shopify side could clarify this

DrewGarratt
Shopify Partner
7 1 11

We are eagerly awaiting an answer as currently, this blocks any site with significant traffic from being deployed to Hydrogen.

 

The framework was clearly designed to use this as a bypass for the rate limits that might well otherwise cause it to fail.

DrewGarratt
Shopify Partner
7 1 11

Update - Still no solution
Shopify's GraphQL Storefront API docs have been updated further with the following

Include your storefront access token as a X-Shopify-Storefront-Access-Token header on all queries that originate from a buyer client, such as a mobile app or browser.

Include your delegate access token as a Shopify-Storefront-Private-Token header on requests from a server, such as the backend of a Hydrogen site.


This further emphasises the need to useShopify-Storefront-Private-Token in requests originating from servers. Most importantly delegate access token docs have still not received any update to reflect how this should be used.

It does appear from tests that including a header as specified above no longer causes storefront endpoints to throw an error, however, you can include anything as a value. So it is very unclear as to whether this token is being validated.

All in all, this continues to be, a mess. One which needs to be urgently addressed in order to allow Hydrogen and Headless projects proper access to Shopify API's in server environments.


Sello_2k
Shopify Partner
9 0 1

For Storefront delegated access tokens you should read this thread:

https://shopify.dev/api/admin-graphql/2022-07/mutations/storefrontaccesstokencreate

DrewGarratt
Shopify Partner
7 1 11

Thanks for the find Sello_2k

That allows us to generate a token but sadly, not to use it.

In order to generate a token using this mutation, you must create a private app with both storefront API and admin API scopes. This mutation can then be triggered.

This will yield what appears to be a valid storefront access token.

In my trials, I was able to make requests to the storefront API `api/2022-07/graphql.json` when using the generated token under the header `X-Shopify-Storefront-Access-Token`.
Unfortunately, if I switched to using this token in the intended header of `Shopify-Storefront-Private-Token` I receive a 403 error.

It should be noted the store this is being on trials on is not a Shopify+ store. But that isn't currently mentioned as a restriction to the use of this token in the documentation.

So it seems we are still stuck.


c10s
Shopify Partner
67 12 27

I'm experiencing the same problem.

 

My suspicion is that the Oxygen sales channel is able to generate these tokens in some currently undocumented/unimplemented way. In either case, documentation needs to be updated to reflect this.


I think this is the case, as I found this comment in their Discord:

 

still early days in our revamp to support better API rate limiting with server to server requests. Right now this is available today for Hydrogen storefronts hosted on Oxygen. We certainly intend to extend this to other server to server request use cases.

Disappointing the documentation doesn't specify this.

DrewGarratt
Shopify Partner
7 1 11

Thankyou C10s. The Storefront API documentation has now been updated twice with language to indicate that we should be using  Shopify-Storefront-Private-Token for server-to-server requests. But as your Discord find reveals this implementation appears to be incomplete.

In the coming week, we hope to test Oxygen to see if it does indeed provide a route to using this header, and whether it is set by the storefrontaccesstokencreate mutation or not.

Here's hoping that the next update either provides us with the missing piece or makes clear that this functionality has additional requirments.

hyperlab
Shopify Partner
4 0 0

Awesome, let us know your findings!

I would assume though that they have ways to make this only work when hosted on the Oxygen platform but would love to be proven wrong...

_JCC_
Shopify Staff
200 27 55

Thanks for your question about this. We're rolling this out incrementally. The first priority was for Hydrogen, and is also why you're able to find general details in our docs. Once we're at 100% rollout we'll update the developer changelog, and provide additional documentation on how to proper utilize the request headers you've identified.

 

I don't have an exact timeline to share today, and while things can change, I feel fairly confident that you'll see this be fully available later this quarter.

John C | Developer Support @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

DrewGarratt
Shopify Partner
7 1 11

Hi _JCC_ thanks so much for contributing to the thread.

I won't mark your answer as the accepted solution just yet, as it's more a promise of an answer to come.

It's good to know that I and other partners aren't utterly mistaken that this is incomplete. 

For the record, my own investigations into even enabling Hydrogen have been met with problems.

So as it stands while we can create valid storefront tokens storefrontaccesstokencreate mutation there is no way to use them with the new Shopify-Storefront-Private-Token header.

_JCC_
Shopify Staff
200 27 55

Hey @DrewGarratt thanks for the feedback, and correct right now it's just a promise of something on it's way.

 

The Hydrogen sales channel that sets up Oxygen for a Hydrogen based custom storefront is only available for plus merchants right now. At some point in the future you'll also see the Hydrogen channel made available to standard and advanced plans. If you're having any problems with the Hydrogen channel on a plus store today please let me know.

 

Finally, I just wanted to correct something. The new headers Shopify-Storefront-Private-Token and Shopify-Storefront-Buyer-IP are intended to be used for server to server requests in the context of the Storefront API. When this is all released the value provided to Shopify-Storefront-Private-Token will be a token created with delegateAccessTokenCreate.

John C | Developer Support @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

_JCC_
Shopify Staff
200 27 55

We're now live 😀 🎊. Change log entry has been posted here with links to documentation.

John C | Developer Support @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

DrewGarratt
Shopify Partner
7 1 11

This is an accepted solution.

Hi _JCC_

Thanks for letting us know the new documentation is up. It looks as if this has been revised a little in the last day or so. But for those looking I've managed to successfully create a token!

What the documentation doesn't make clear is what has changed. It is now possible to create a delegate access token with various unauthenticated scopes. 

Below is the GraphQL admin API mutation required to create a delegate token with the correct access scopes to be used in the Shopify-Storefront-Private-Token header. The access scope list used is identical to that of a token created using the storefrontAccessTokenCreate mutation.

mutation {
  delegateAccessTokenCreate(input: { delegateAccessScope: [
    "unauthenticated_read_content",
    "unauthenticated_read_customer_tags",
    "unauthenticated_read_product_tags",
    "unauthenticated_read_product_inventory",
    "unauthenticated_read_product_listings",
    "unauthenticated_write_checkouts",
    "unauthenticated_read_checkouts",
    "unauthenticated_write_customers",
    "unauthenticated_read_customers",
    "unauthenticated_read_selling_plans",
    "unauthenticated_read_product_pickup_locations"
   ] 
  })
  {
    delegateAccessToken {
      accessToken
    }
    shop {
      id
    }
    userErrors {
      field
      message
    }
  }
}


It would be great if we could see the delegate access token documentation updated with a list of valid scope strings and perhaps even an example like the above 😊

codeleter
Shopify Partner
4 0 0

I  got the message , so the api changed again?

 

"message": "is invalid: cannot delegate access scope other than: write_content, write_themes, write_products, write_product_listings, write_customers, write_draft_orders, write_script_tags, write_inventory, write_fulfillments, write_assigned_fulfillment_orders, write_merchant_managed_fulfillment_orders, write_third_party_fulfillment_orders, write_checkouts, write_reports, write_price_rules, write_marketing_events, write_resource_feedbacks, read_analytics, read_all_orders, write_orders, write_channels, read_apps, write_translations, write_locales, write_discounts, write_shipping, write_order_edits, write_legal_policies, unauthenticated_read_product_listings, unauthenticated_read_product_tags, unauthenticated_write_checkouts, unauthenticated_write_customers, unauthenticated_read_customer_tags, unauthenticated_read_content"

 

_JCC_
Shopify Staff
200 27 55

Hey @codeleter you should only get this message if you're asking for a scope that the app being used to generate the delegate access token does not already have. Double check that the access scopes being sent to delegateAccessTokenCreate call all already present on the app being used to generate the delegate.

John C | Developer Support @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

benbenben-bb
New Member
4 0 0

I'm a bit confused by the documentation. 

 

Are there any limitations between basic, standard, and advanced Shopify plans wrt delegate access rights?

 

If I naively execute the sample query in the Shopify_GraphiQL_App for my shop (within the shop admin page), I only have a handful of "read" delegate access scopes available:

Screen Shot 2022-10-23 at 10.34.44 AM.png

 

it would be very helpful for documentation to walk through the process of getting from a hydrogen store's API key to a delegate access token (in particular, being a bit more explicit about the intermediary API call for an access token, which I'm guessing is my current issue).

 

benbenben-bb
New Member
4 0 0

edit: the hang up on my end was figuring out that, for an app created via the admin dashboard, I needed to create a separate access token for the admin API with appropriate permissions. With that access token in hand, the graphQL worked just fine (although I don't believe it's possible to query with an access token via the Shopify_GraphiQL_App)

codeleter
Shopify Partner
4 0 0

I found the reason. it's similar to what @benbenben-bb  said, I can't run the query in Shopify GraphQL App, I need to use an admin token and run it outside via Curl or Postman.