Shopify Flow Authentication Shows 401 error

I have created this basic action flow extension

[[extensions]]
name = "bestseller products"
handle = "bestseller-products"
type = "flow_action"
uid = "<uuid>"
description = "Your description"
runtime_url = "https://suffered-functional-deserve-pretty.trycloudflare.com/api/getBestSeller"

[settings]

  [[settings.fields]]
  type = "customer_reference"
  required = true

  [[settings.fields]]
  type = "single_line_text_field"
  key = "your-field-key"
  name = "Display name"
  description = "A description of my field"
  required = true

created a file called api.getBestSeller.ts

import { ActionFunctionArgs, json } from "@remix-run/node";
import { authenticate, unauthenticated } from "app/shopify.server";

export const action = async ({ request }: ActionFunctionArgs) => {
    const { payload, session } = await authenticate.flow(request);
    const shop = session?.shop || payload?.shop_domain;
    try {
        const { admin } = await unauthenticated.admin(shop);
        const response = await admin.graphql(
            `#graphql
            query {
                products(first: 10, sortKey: BEST_SELLING) {
                    edges {
                        node {
                            id
                            title
                            handle
                        }
                    }
                }
            }`
        );

        const resJson = await response.json();

        if (resJson.errors) {
            console.error("GraphQL logic errors:", JSON.stringify(resJson.errors, null, 2));
            return json({ error: "GraphQL Error" }, { status: 500 });
        }

        console.log("Success! Top Sellers:", JSON.stringify(resJson.data.products.edges, null, 2));
        return json({ 
            bestSellers: resJson.data.products.edges.map(edge => edge.node.title).join(", ") 
        });

    } catch (error) {
        console.error("Critical Failure:", error);
        return json({ error: "Unauthorized" }, { status: 401 });
    }
}

i can see the app running fine in the terminal also doesn’t show any error.

flow detects and runs the action. its just that i keep getting 401

23:03:35 β”‚                     remix β”‚ [shopify-app/INFO] Authenticating flow request
23:03:36 β”‚                     remix β”‚ Critical Failure: HttpResponseError: Received an error response (401 Unauthorized) from Shopify:
23:03:36 β”‚                     remix β”‚ {
23:03:36 β”‚                     remix β”‚   "networkStatusCode": 401,
23:03:36 β”‚                     remix β”‚   "message": "GraphQL Client: Unauthorized",
23:03:36 β”‚                     remix β”‚   "response": {}
23:03:36 β”‚                     remix β”‚ }
23:03:36 β”‚                     remix β”‚   response: {
23:03:36 β”‚                     remix β”‚     code: 401,
23:03:36 β”‚                     remix β”‚     statusText: 'Unauthorized',
23:03:36 β”‚                     remix β”‚     body: { errors: [Object] },
23:03:36 β”‚                     remix β”‚     headers: {
23:03:36 β”‚                     remix β”‚       'Alt-Svc': [Array],
23:03:36 β”‚                     remix β”‚       'Cf-Cache-Status': [Array],
23:03:36 β”‚                     remix β”‚       'Cf-Ray': [Array],
23:03:36 β”‚                     remix β”‚       Connection: [Array],
23:03:36 β”‚                     remix β”‚       'Content-Security-Policy': [Array],
23:03:36 β”‚                     remix β”‚       'Content-Type': [Array],
23:03:36 β”‚                     remix β”‚       Date: [Array],
23:03:36 β”‚                     remix β”‚       Nel: [Array],
23:03:36 β”‚                     remix β”‚       'Referrer-Policy': [Array],
23:03:36 β”‚                     remix β”‚       'Report-To': [Array],
23:03:36 β”‚                     remix β”‚       'Reporting-Endpoints': [Array],
23:03:36 β”‚                     remix β”‚       Server: [Array],
23:03:36 β”‚                     remix β”‚       'Server-Timing': [Array],
23:03:36 β”‚                     remix β”‚       'Strict-Transport-Security': [Array],
23:03:36 β”‚                     remix β”‚       'Transfer-Encoding': [Array],
23:03:36 β”‚                     remix β”‚       'Www-Authenticate': [Array],
23:03:36 β”‚                     remix β”‚       'X-Content-Type-Options': [Array],
23:03:36 β”‚                     remix β”‚       'X-Dc': [Array],
23:03:36 β”‚                     remix β”‚       'X-Download-Options': [Array],
23:03:36 β”‚                     remix β”‚       'X-Frame-Options': [Array],
23:03:36 β”‚                     remix β”‚       'X-Permitted-Cross-Domain-Policies': [Array],
23:03:36 β”‚                     remix β”‚       'X-Request-Id': [Array],
23:03:36 β”‚                     remix β”‚       'X-Shardid': [Array],
23:03:36 β”‚                     remix β”‚       'X-Shopid': [Array],
23:03:36 β”‚                     remix β”‚       'X-Sorting-Hat-Podid': [Array],
23:03:36 β”‚                     remix β”‚       'X-Sorting-Hat-Shopid': [Array],
23:03:36 β”‚                     remix β”‚       'X-Xss-Protection': [Array]
23:03:36 β”‚                     remix β”‚     }
23:03:36 β”‚                     remix β”‚   }

i have these scopes added

scopes = "customer_read_companies,customer_write_companies,read_content,read_customers,read_discounts,read_inventory,read_locations,read_metaobject_definitions,read_metaobjects,read_orders,read_products,write_content,write_customers,write_discounts,write_metaobject_definitions,write_metaobjects,write_orders,write_products,read_reports"
  • i tried both authenticate.flow and unauthenticated.admin
  • i tried autenticate.admin and it gave me this
23:27:08 β”‚                     remix β”‚ [shopify-app/INFO] Authenticating flow request
23:27:08 β”‚                     remix β”‚ Critical Failure: Response {
23:27:08 β”‚                     remix β”‚   status: 410,
23:27:08 β”‚                     remix β”‚   statusText: 'Gone',
23:27:08 β”‚                     remix β”‚   headers: Headers {},
23:27:08 β”‚                     remix β”‚   body: null,
23:27:08 β”‚                     remix β”‚   bodyUsed: false,
23:27:08 β”‚                     remix β”‚   ok: false,
23:27:08 β”‚                     remix β”‚   redirected: false,
23:27:08 β”‚                     remix β”‚   type: 'default',
23:27:08 β”‚                     remix β”‚   url: ''
23:27:08 β”‚                     remix β”‚ }
  • i tried restarting the app β†’ visiting the app’s page β†’ then create the workflow again and triggering the node
  • tried different queries

is there anything else i can try to fix this.

i need to query 2 things.

  • best seller products. analytics api sounds more accurate for the use-case
  • recently created products

idea is to periodically run a flow to first remove β€œnew” and β€œbestseller” tags from products and then add these tags to the updated products

This line is safely accessing either the session or the payload attributes. In theory both could be empty and it would move to the next operation of sending that GraphQL request.

Have you tried logging the shop variable after assignment? That might help narrow down the issue.

1 Like

i still get 401 unauthorized

    } catch (error) {
        console.log(session.shop)
        console.log(session)
        console.error("Critical Failure:", error);
        return json({ error: "Unauthorized" }, { status: 401 });
    }
10:41:37 β”‚                     remix β”‚ quickstart-752c32e6.myshopify.com
10:41:37 β”‚                     remix β”‚ Session {
10:41:37 β”‚                     remix β”‚   id: 'offline_quickstart-752c32e6.myshopify.com',
10:41:37 β”‚                     remix β”‚   shop: 'quickstart-752c32e6.myshopify.com',
10:41:37 β”‚                     remix β”‚   state: '',
10:41:37 β”‚                     remix β”‚   isOnline: false,
10:41:37 β”‚                     remix β”‚   scope:
'customer_write_companies,read_inventory,read_locations,write_content,write_customers,write_discounts,write_metaobject_definitions,write_metaobjects,write_orders,write_products',
10:41:37 β”‚                     remix β”‚   expires: undefined,
10:41:37 β”‚                     remix β”‚   accessToken: '<accessToken>',
10:41:37 β”‚                     remix β”‚   onlineAccessInfo: undefined
10:41:37 β”‚                     remix β”‚ }
10:41:37 β”‚                     remix β”‚ Critical Failure: Response {
10:41:37 β”‚                     remix β”‚   status: 410,
10:41:37 β”‚                     remix β”‚   statusText: 'Gone',
10:41:37 β”‚                     remix β”‚   headers: Headers {},
10:41:37 β”‚                     remix β”‚   body: null,
10:41:37 β”‚                     remix β”‚   bodyUsed: false,
10:41:37 β”‚                     remix β”‚   ok: false,
10:41:37 β”‚                     remix β”‚   redirected: false,
10:41:37 β”‚                     remix β”‚   type: 'default',
10:41:37 β”‚                     remix β”‚   url: ''
10:41:37 β”‚                     remix β”‚ }

So that proves the webhook auth and shop details are included. That’s a good start.

It’s possible that this shop’s access token is invalid. Perhaps the app was uninstalled or reinstalled and new access token was issued but not saved properly.

Have you tried sending a Shopify Admin API request with that access token to confirm it’s valid?