Reposting this here as I’m thinking it is likely more relevant to POS extensions.
I’ve got a merchant with an interesting issue, they are unable to use my POS extension due to an authentication issue. I checked my server logs for some of their requests coming from the extension and I can see the following debug message -
Responding to invalid Shopify ID token: Missing Shopify ID Token
I’m wondering how it’s possible that their requests do no include a Shopify ID Token?
I can provide more details of the requests if that helps, just let me know what you need.
Hey again @simon_b - thanks for reposting this here, this is probably the right spot for it for sure.
That error generally means the request is reaching your backend without a bearer token attached. In POS UI extensions, you’ll want to call shopify.session.getSessionToken() before making the backend request, then pass it through as:
Authorization: `Bearer ${token}`
One thing I’d check for this merchant specifically: getSessionToken() can return undefined if the authenticated POS user doesn’t have the right app permissions. The token is based on the logged-in Shopify user, not necessarily the pinned staff member in POS.
So I’d confirm:
whether getSessionToken() is resolving to a token, returning undefined, or throwing
whether the backend request is only sent after a token is available
whether the failing requests include an Authorization header at all, with the value redacted
If you’re already doing all of that, could you share a small redacted snippet of the fetch code, plus the POS version/platform? Happy to help dig further from there.
It sounds like the getSessionToken call is returning undefined as you described. Sounds like I should add a guard clause for the presence of the session token and display a message about permissions in that situation? Or can it fail to return a token for other reasons? I’ve noticed it can timeout sometimes.
So possibly it’s a permissions issue but the strange thing is that this is occurring for the store owner account, which I’d assume has full permissions. I suspected this was the issue initially so I asked the merchant to check permissions but they assured me that the account has administrator permissions. Could there be something else at play here?
EDIT - We are using 2025-07 / pos.home.modal.render, and the merchant said they are running the latest version of POS.
I little more context, the merchant mentioned this when they contacted me this week:
We are having issues with authentication once again.
Since your last email, we created a new user, User1, and have been successful authenticating and using the app. The user User2 could not authenticate.
However, this morning, we arrived to see that Shopify had logged us out of our POS system, for whatever reasons. Upon logging back in, User1 has not been able to authenticate with the app either.
I’m thinking I could ask the merchant to reproduce the issue on their device and capture the logs and send them to you, just wondering what the best way is to ensure they get to you?
Hey @simon_b - thanks for the extra context, that helps, sorry for the delayed reply, just catching up on the forums here!
Based on what you shared, I’d treat this as getSessionToken() returning a missing value before the request is sent. One thing to watch for is that Authorization: Bearer ${await api.session.getSessionToken()} can still send Bearer undefined, which your backend may interpret as a missing Shopify ID token.
I’d add a guard so the request only fires after a token is present, and log only whether the token was present/missing/timed out, not the token itself. Could you also have the merchant confirm the app is enabled under the POS sales channel’s POS apps area, and confirm the exact POS app version/platform?
For logs, have them reproduce the issue, then in Shopify POS go to Support > Report a bug and include Alan_G, the app name, and this thread title. Once they send that, just let me know the date/time it was submitted and I can try to pull it up on our end. Hope this helps!
Hi @Alan_G thank you for the response, I’ve asked the merchant to send through some logs, although they seem to have gone quiet now so I’m not sure if they will actually do it.
No worries - feel free to ping me here if they do send those out and I can take a look - we do store those logs for a little while once they’re sent out, so I should be able to retrieve them even if it’s been a while. Let me know if I can help out with anything else as always!
I was able to grab those logs, and from what I can see, the extension itself is loading successfully in POS. I can see the pos.home.tile.render target render, and later the pos.home.modal.render target render as well. During that modal load, POS also logs the session token generation request as completing successfully on our end.
So based on these logs, I’m not seeing POS failing to generate the session token for this reproduction. I also don’t see evidence in the POS logs of getSessionToken() returning undefined at the point the modal loads.
The next thing I’d check is the app-side request path. I’d just make sure the backend request is only sent after await api.session.getSessionToken() resolves to a truthy value, and log whether the outgoing request has an Authorization header before sending it. I’d also avoid constructing Authorization: Bearer ${await api.session.getSessionToken()} inline, since that can still send Bearer undefined if the token call ever returns a missing value.
One extra note: these logs were captured during an incident that affected POS yesterday, so if the merchant’s issue happened during that window it may have made things noisier, but I don’t see a token-generation failure for the extension in the logs provided.
Let me know if you can share the timestamp of a backend request that returned “Missing Shopify ID Token” and whether that request’s Authorization header was present/redacted on your side. That should help narrow down whether the token is missing before the request is sent and I can pull some more logs, or whether something in the app/server request handling is dropping it. Hope this helps a bit as always!
I’d just make sure the backend request is only sent after await api.session.getSessionToken() resolves to a truthy value
Are you saying it is possibly a race condition here? These failing requests are made when the app first loads so perhaps that is what’s happening. I’m thrown though as it sounds like you saw no evidence of getSessionToken returning a falsey value in the logs.
I could add a retry to the getSessionToken call in the event that it returns a falsey value?
I have two timestamps for failed backend requests from the merchant that occurred around the time that the logs were collected:
2026-06-03T20:00:44.791282
2026-06-03T20:00:44.791417
Unfortunately we don’t log the Auth header, but both of these requests resulted in the error:
[ ShopifyApp | DEBUG | Shop Not Found ] Responding to invalid Shopify ID token: Missing Shopify ID Token
So that suggests that the auth token was missing in the request sent from the device, so potentially getSessionToken returned null / undefined.
I went ahead and added the retry mechanism to the session token API call and now I can see instances where this is occuring for other merchants, where I retry 3 times and it still returns an empty string, so it’s not a race condition.
Hey @simon_b - thanks for the follow-up here, and thanks for your patience on my delayed reply.
Given you’re still seeing an empty string after retries, I agree this doesn’t sound like a race condition at this point. The main thing I’d want to rule out next is the logged-in Shopify user’s app-specific permissions. The token is tied to the authenticated Shopify user in POS, not just the pinned POS staff member if that makes sense, so could you have the merchant confirm the user role in Admin > Settings > Users includes access to your app?
For the next failing repro, could you also share:
POS platform and exact POS app version
whether getSessionToken() returns null, undefined, “”, times out, or throws
elapsed time for each retry
UTC timestamp of the failed backend request
If they can send a fresh POS bug report right after reproducing it and include Alan_G, the app name, and this thread title, that would be super helpful as well and I can try to line that up with what we see on our end. I’ll also check internally whether repeated empty-string returns are expected in any permission state here.
Is there any way for you to determine the user account and permissions using the logs they sent previously? They mentioned to me in a previous correspondence that they were using the store owner account so that would suggest they do have permissions, but I have no way of confirming this and they are understandably out of patience with us I think, it’s been quite a while they have been locked out of using the app now.
The other instances I saw of this error occurred on a couple of different stores after I added the retry mechanism:
Jun 8, 23:18:00 UTC
Shop ID: 28092432481
Staff ID: 41173975137
Jun 6, 10:35:41 UTC
Shop ID: 28915433575
Staff ID: 71391412327
Jun 6, 01:12:59 UTC
Shop ID: 69378867447
Staff ID: 114164334839
They are all on iPad and on versions 11.7.1 and 11.7.2.
I added a 10s timeout to each request for a token, and retry 3 times before erroring. I am checking for a falsey token, and then raising an error if found, which I capture with our error monitoring software, it looks like the tokens are returning as ““ for these instances.
Because I can’t use the library that comes with our error monitoring software on the POS I had to write my own code to track behaviour / breadcrumbs leading up to the error so some of the context you’re after may be missing, plus the stack traces are all minified and useless.
One of my merchants reported the problem as I show an error message as a toast when these occur, I asked them to send you logs if they continue to see it but I haven’t heard back from them. They may have done so and just not told me, would you be alerted if they did? It was Shop ID 28915433575.