I’m building a public API route in my Shopify Remix Public application. In a regular application, it’s straightforward to use GraphQL Admin queries with authenticator.admin, but how can we create and access GraphQL queries in a public API route? Since authentication doesn’t work the same way, we can’t rely on authenticator.admin, right?
Should we use unautheticated.admin(shop_domain) ?
Whats the secure/appropriate way to use admin graphQL API
For public API routes, you cannot use unauthenticated.admin(shop_domain) as it does not provide the necessary authentication for Admin API access. Some good docs to describe how auth for Shopify apps works are:
I read the docs, but they’re quite confusing. I’m not sure if I’m understanding this correctly, but do we need to use a Shopify Admin library to pass the shop and access the token? Currently, I store the offline access token in my database. The documentation is unclear, especially since I’m using the Shopify Remix template, where I rely on authenticator.admin for internal GraphQL API queries. However, I’m unsure how to authenticate requests when building a public API route. Do I need to fetch the shop token and use it to create an Admin API client before making requests? A clear explanation would be really helpful.
So what @Liam-Shopify is referring to is when the request is coming from the embedded Admin.
But it sounds like the context in your case is a request to a public API route, not necessarily from a session by that particular merchant in your app in the admin.
If that’s the case, then you’ll need to query those merchant’s OAuth access token in your database and send them as part of your GraphQL query.
I’m not aware of a helper method in Remix to bypass request authentication and instead load an authenticated Admin GraphQL instance simply by the *.myshopify.com key, but you could do that yourself with your database and this client.
Thanks, @Liam-Shopify and @Dylan. I have a better understanding now. I went through the GitHub repo and found two approaches, but I need some clarification on their purpose. Let me provide more context for my case.
In my Shopify Remix template, I created a public API route that will be triggered by an AWS Lambda function to send data. From there, I need to call the GraphQL Admin API to query store data and perform internal calculations. I came across two methods—one of which I’m currently using in an unauthenticated way, but as Liam mentioned, it’s not the most secure approach. I’d appreciate some clarification on which method would be best suited for my scenario.
In my Shopify Remix template, I created a public API route that will be triggered by an AWS Lambda function to send data. From there, I need to call the GraphQL Admin API to query store data and perform internal calculations.
You should still implement some kind of API token authentication for your Lambda’s request, just to make sure it can’t be abused. Especially if this Remix route is going to respond with merchant data - which Example 1 looks like it is doing.
I’m sure you’re aware of this, but just want to make it clear.
In Example 1, where is this getShopFromExternalRequest function defined? Is it featured within the official Shopify Remix template? I’m just not sure how this function is possibly finding the shop record from an unauthenticated request. Is it relying on the HTTP headers or body?
That question needs to be answered before your Lambda can send a request that routes to the correct shop record.
Both examples are most likely equivalent. Under the hood, getShopFromExternalRequest might be querying your database for the merchant’s record and creating an instance of a Shopify GraphQL client with that merchant’s token.
Example #2 is just doing that work by hand, even though you’ve hardcoded a specific merchant’s credentials, I assume replace that with a database query instead.
@Dylan
The previous example was from the API library you mentioned. In my case, I’m doing something similar.
I send a specific topic to AWS SQS, and when a message enters the queue, it triggers a Lambda function. The Lambda function then makes an HTTP request to my public API route, which includes HMAC validation for the secret key.
After that, I perform a database query using the account ID received from the Lambda request to retrieve the store’s domain name. Then, I use the following approach:
Public Api route
1. hmac validation for lambda request
2. db query to get shop domain with accountID from lambda request.
3. instantiate admin api by below method
await unauthenticated.admin(account.platformDomain);
Once this is set up, I make a GraphQL query based on the required data. This setup works fine, but my main confusion is whether I should use the API library to instantiate the GraphQL client with the store’s domain and access token (retrieved from the database) or if I should continue using unauthenticated.admin to access the Admin API.
Thanks @Dylan for the help . Much appreciated. Based on what @Liam-Shopify stated above. i assume the way i approach the unauthenticate method is corrrect.
@Liam-Shopify Let me know if you find anything else regarding this approach. will be helpful