I currently have an issue. In my business scenario, there are cases where I need to use the admin API to create free draft orders for users who have subscribed to my service. In these cases, I need to verify whether the user initiating the request is the currently logged-in user.
Here is my business process:
Users subscribe to our product, and the backend records this information in the database (DB).
Each user has one opportunity to purchase items for free once a month, and they can select the products they want on our designated pages.
When the user clicks “Buy Now”, the system verifies the customer ID passed from the frontend, then calls the admin API to generate a draft order and returns a checkout link.
The frontend renders the checkout link.
The user clicks “Complete” to generate an official order.
The subsequent order fulfillment process proceeds.
In reality, there is a serious security risk when generating draft orders:
Once the draft order is generated and the checkout link is returned, anyone who obtains this link can modify the shipping address within the link. When initiating a draft order request, I can only verify whether the passed customer ID is subscribed and whether an order has already been placed this month—I cannot effectively verify whether the current user is the logged-in user.
In this case, an attacker could guess the customer IDs of certain users, then illegally request the draft order creation API, place an order by impersonating a subscribed user, and finally change the address to the attacker’s own shipping address.
Currently, I can only add an extra redundant email verification code step to ensure the operator is the owner of the email address after clicking “Buy Now“. I have not found a good way to simplify this step while ensuring that the user requesting my backend API is the currently logged-in user.
Although there are independent Shopify interaction requests on website pages (such as the profile page), the Authorization and cookies used for these requests seem unable to be reused in my draft order generation API for user verification.
Authenticate customers with Storefront API customer access tokens. The Frontend sends the logged in customerAccessToken to your backend. Backend queries Storefront API to verify that the token matches the requested customer ID before creating the draft order. Additionally, implement one-time signed nonces, rate limits, and an optionally email OTP for further protection.
Without using a costly verification service your overthinking this or framing it wrong if not an outright xyproblem.
goal: is order valid
that is NOT the same as is customer valid(that is very vague and costly)
new orders should just match what’s on record
If records don’t match then order needs manual review
“record” here means you store addresses somewhere like in metafields/metaobjects so customers can’t just change them without review/process.
Otherwise what are you gonna do collect government ids? Asking for a photo/video at time of purchase? etc etc etc
According to our frontend colleagues, however, there seems to be no elegant way to obtain and pass the Storefront Access Token to the backend, as this is an operation independent of our standalone website.
Therefore, I am not sure whether using the Storefront for verification can achieve user verification.
You’re absolutely right that verifying the user’s information and address after they place an order is a simple and efficient solution. However, in reality, to enhance the user experience, users are allowed to directly modify their own shipping address without going through our customer service. Therefore, it is essential to verify that the currently passed customer ID belongs to the owner of the current account when submitting a checkout request to generate a draft order. This is because once the checkout link is successfully generated, the shipping address can be modified freely on the checkout page.
Currently, we use secondary email verification + CAPTCHA for our zero-cost purchase API to raise the bar for potential attacks. In fact, to further enhance the user experience, I am wondering if there are other ways to eliminate the email verification step—for example, by leveraging Shopify’s Storefront Access Token and letting the backend handle the verification. According to our frontend colleagues, however, there seems to be no elegant way to obtain and pass the Storefront Access Token to the backend, as this is an operation independent of our standalone website.
since no money is changing hands that is up to the owner of the email address to keep it private. the system is set up for people to PURCHASE items. when that happens there is verification based on the credit card, address, etc. same system for unsolicited orders or drafts. if you want to use the system for something other than that and are simply sending emails to people with free links Shopify cannot help you. there is no security risk as anyone can share an email at any time with anyone. its an email and not a financial transaction
Not seem a scalable route, especially for some business models or regulated goods.
It’s a system where people can sell or distribute there subscription with no friction.
So there will always be side effects in a loose system like that.
The juggling of building for the storefront-api is just another complexity modifier ontop of the problem.
For dev related builds see the dev forum community.shopify.dev