Trouble authenticating a request from a POS UI extension

Topic summary

A developer encountered issues authenticating requests from a POS UI extension to their Remix app. They initially tried using authenticate.public.appProxy(request) or authenticate.admin(request) but faced errors.

Initial Problem:

  • Successfully retrieved session token in the POS UI extension
  • Received “Query does not contain a signature value” error when not using the token
  • Got empty errors when using it as a Bearer token

Solution Found:

  • Pass the session_token as a Bearer token in the fetch request
  • On the Remix side, use authenticate.admin(request) for standard cases
  • As a fallback for error handling, manually verify the JWT using:
    const decoded = jwt.verify(token, process.env.SHOPIFY_API_SECRET, { algorithms: ["HS256"] })
    

The issue was resolved by properly implementing the session token authentication flow between the POS extension and Remix backend.

Summarized with AI on November 8. AI used: claude-sonnet-4-5-20250929.

Hi,

I’ve been trying to authenticate a request from a POS UI extension to my Remix app.

I want to use:

const { admin } = await authenticate.public.appProxy(request);

or:

const { admin } = await authenticate.admin(request);

In my POS UI extension, I’m able to get the session token:

const [sessionToken, setSessionToken] = useState<string | null | undefined>(
    null,
  );

  useEffect(() => {
    getSessionToken().then((token) => {
      setSessionToken(token);
    });
  }, [shopDomain, getSessionToken]);

But I cannot find any details about authenticating the request.
If I’m using it as a Bearer token, I get:

shopify-app/INFO] Query does not contain a signature value

And if I don’t use any, I get an empty error.

What do I do wrong ?

Actually, here was the solution:

Use the session_token and pass it as a Bearer in the fetch request.

On remix, use:

const session = await authenticate.admin(request);

But, in case of any error, I use:

const decoded = jwt.verify(token, process.env.SHOPIFY_API_SECRET!, {
algorithms: ["HS256"],
});