Shopify / cli

Build apps, themes, and hydrogen storefronts for Shopify
https://shopify.dev
MIT License
433 stars 130 forks source link

[Bug]: Missing Authorization header, was the request made with authenticatedFetch? Session was not valid. Redirecting to /api/auth?shop=undefined #2660

Closed SeaworldSolo closed 1 year ago

SeaworldSolo commented 1 year ago

Please confirm that you have:

In which of these areas are you experiencing a problem?

App, Theme

Expected behavior

Trying to validate whether address on Cart-Page is within delivery range. If yes, allow checkout. If no, disable checkout.

Set up Shopify CLI & Node App template. Able to listen to webhooks.

Webhookhandlers.js:

import { DeliveryMethod } from "@shopify/shopify-api";

/**
 * @type {{[key: string]: import("@shopify/shopify-api").WebhookHandler}}
 */
export default {
  ORDERS_CREATE: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      console.log('--- ORDER CREATE ---');
      const payload = JSON.parse(body);
      console.log(payload);
      console.log('--- /ORDER CREATE ---');
    }
  },
  PRODUCTS_UPDATE: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      console.log('--- Product update ---');
      const payload = JSON.parse(body);
      console.log(payload);
      console.log('--- /Product update ---');
    }
  },
  /**
   * Customers can request their data from a store owner. When this happens,
   * Shopify invokes this webhook.
   *
   * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#customers-data_request
   */
  CUSTOMERS_DATA_REQUEST: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      const payload = JSON.parse(body);
      // Payload has the following shape:
      // {
      //   "shop_id": 954889,
      //   "shop_domain": "{shop}.myshopify.com",
      //   "orders_requested": [
      //     299938,
      //     280263,
      //     220458
      //   ],
      //   "customer": {
      //     "id": 191167,
      //     "email": "john@example.com",
      //     "phone": "555-625-1199"
      //   },
      //   "data_request": {
      //     "id": 9999
      //   }
      // }
    },
  },

  /**
   * Store owners can request that data is deleted on behalf of a customer. When
   * this happens, Shopify invokes this webhook.
   *
   * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#customers-redact
   */
  CUSTOMERS_REDACT: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      const payload = JSON.parse(body);
      // Payload has the following shape:
      // {
      //   "shop_id": 954889,
      //   "shop_domain": "{shop}.myshopify.com",
      //   "customer": {
      //     "id": 191167,
      //     "email": "john@example.com",
      //     "phone": "555-625-1199"
      //   },
      //   "orders_to_redact": [
      //     299938,
      //     280263,
      //     220458
      //   ]
      // }
    },
  },

  /**
   * 48 hours after a store owner uninstalls your app, Shopify invokes this
   * webhook.
   *
   * https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks#shop-redact
   */
  SHOP_REDACT: {
    deliveryMethod: DeliveryMethod.Http,
    callbackUrl: "/api/webhooks",
    callback: async (topic, shop, body, webhookId) => {
      const payload = JSON.parse(body);
      // Payload has the following shape:
      // {
      //   "shop_id": 954889,
      //   "shop_domain": "{shop}.myshopify.com"
      // }
    },
  },
};

Setup an in endpoint in App.js to receive the address information:

// @ts-check
import { join } from "path";
import { readFileSync } from "fs";
import express from "express";
import serveStatic from "serve-static";

import shopify from "./shopify.js";
import productCreator from "./product-creator.js";
import webhookHandlers from "./webhook-handlers.js";

const PORT = parseInt(
  process.env.BACKEND_PORT || process.env.PORT || "3000",
  10
);

const STATIC_PATH =
  process.env.NODE_ENV === "production"
    ? `${process.cwd()}/frontend/dist`
    : `${process.cwd()}/frontend/`;

const app = express();

// Set up Shopify authentication and webhook handling
app.get(shopify.config.auth.path, shopify.auth.begin());
app.get(
  shopify.config.auth.callbackPath,
  shopify.auth.callback(),
  shopify.redirectToShopifyOrAppRoot()
);
app.post(
  shopify.config.webhooks.path,
  shopify.processWebhooks({webhookHandlers})
);

// If you are adding routes outside of the /api path, remember to
// also add a proxy rule for them in web/frontend/vite.config.js

app.use("/api/*", shopify.validateAuthenticatedSession());

app.use(express.json());

app.get("/api/products/count", async (_req, res) => {
  const countData = await shopify.api.rest.Product.count({
    session: res.locals.shopify.session,
  });
  res.status(200).send(countData);
});

app.get("/api/products/create", async (_req, res) => {
  let status = 200;
  let error = null;

  try {
    await productCreator(res.locals.shopify.session);
  } catch (e) {
    console.log(`Failed to process products/create: ${e.message}`);
    status = 500;
    error = e.message;
  }
  res.status(status).send({ success: status === 200, error });
});

app.use(shopify.cspHeaders());
app.use(serveStatic(STATIC_PATH, { index: false }));

// Code for pre-order-validation

app.use("/api/requestelivery", async(req,res) => {
    const { body } = req;
    let status = 200
    let error = null
    console.log(body)

  res.status(200).send({success: status === 200, error})
});

app.use("/*", shopify.ensureInstalledOnShop(), async (_req, res, _next) => {
  return res
    .status(200)
    .set("Content-Type", "text/html")
    .send(readFileSync(join(STATIC_PATH, "index.html")));
});

app.listen(PORT);

Actual behavior

Occasionally Get Cors error from cart page:

Access to fetch at 'https://dbdb-142-114-91-106.ngrok-free.app/api/auth?shop=undefined' (redirected from 'https://dbdb-142-114-91-106.ngrok-free.app/api/requestdelivery') from origin 'https://partyondelivery.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

and from the server:

21:21:37 │ web-backend │ [shopify-api/INFO] Receiving webhook request 21:21:37 │ web-backend │ --- ORDER CREATE --- 21:21:37 │ web-backend │ { 21:21:37 │ web-backend │ id: 820982911946154500, 21:21:37 │ web-backend │ admin_graphql_api_id: 'gid://shopify/Order/820982911946154508', 21:21:37 │ web-backend │ app_id: null, 21:21:37 │ web-backend │ browser_ip: null, 21:21:37 │ web-backend │ buyer_accepts_marketing: true, 21:21:37 │ web-backend │ cancel_reason: 'customer', 21:21:37 │ web-backend │ cancelled_at: '2021-12-31T19:00:00-05:00', 21:21:37 │ web-backend │ cart_token: null, 21:21:37 │ web-backend │ checkout_id: null, 21:21:37 │ web-backend │ checkout_token: null, 21:21:37 │ web-backend │ client_details: null, 21:21:37 │ web-backend │ closed_at: null, 21:21:37 │ web-backend │ confirmation_number: null, 21:21:37 │ web-backend │ confirmed: false, 21:21:37 │ web-backend │ contact_email: 'jon@example.com', 21:21:37 │ web-backend │ created_at: '2021-12-31T19:00:00-05:00', 21:21:37 │ web-backend │ currency: 'USD', 21:21:37 │ web-backend │ current_subtotal_price: '398.00', 21:21:37 │ web-backend │ current_subtotal_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '398.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '398.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ current_total_additional_fees_set: null, 21:21:37 │ web-backend │ current_total_discounts: '0.00', 21:21:37 │ web-backend │ current_total_discounts_set: { 21:21:37 │ web-backend │ shop_money: { amount: '0.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '0.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ current_total_duties_set: null, 21:21:37 │ web-backend │ current_total_price: '398.00', 21:21:37 │ web-backend │ current_total_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '398.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '398.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ current_total_tax: '0.00', 21:21:37 │ web-backend │ current_total_tax_set: { 21:21:37 │ web-backend │ shop_money: { amount: '0.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '0.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ customer_locale: 'en', 21:21:37 │ web-backend │ device_id: null, 21:21:37 │ web-backend │ discount_codes: [], 21:21:37 │ web-backend │ email: 'jon@example.com', 21:21:37 │ web-backend │ estimated_taxes: false, 21:21:37 │ web-backend │ financial_status: 'voided', 21:21:37 │ web-backend │ fulfillment_status: 'pending', 21:21:37 │ web-backend │ landing_site: null, 21:21:37 │ web-backend │ landing_site_ref: null, 21:21:37 │ web-backend │ location_id: null, 21:21:37 │ web-backend │ merchant_of_record_app_id: null, 21:21:37 │ web-backend │ name: '#9999', 21:21:37 │ web-backend │ note: null, 21:21:37 │ web-backend │ note_attributes: [], 21:21:37 │ web-backend │ number: 234, 21:21:37 │ web-backend │ order_number: 1234, 21:21:37 │ web-backend │ order_status_url: 'https://jsmith.myshopify.com/548380009/orders/123456abcd/authenticate?key=abcdefg', 21:21:37 │ web-backend │ original_total_additional_fees_set: null, 21:21:37 │ web-backend │ original_total_duties_set: null, 21:21:37 │ web-backend │ payment_gateway_names: [ 'visa', 'bogus' ], 21:21:37 │ web-backend │ phone: null, 21:21:37 │ web-backend │ po_number: null, 21:21:37 │ web-backend │ presentment_currency: 'USD', 21:21:37 │ web-backend │ processed_at: null, 21:21:37 │ web-backend │ reference: null, 21:21:37 │ web-backend │ referring_site: null, 21:21:37 │ web-backend │ source_identifier: null, 21:21:37 │ web-backend │ source_name: 'web', 21:21:37 │ web-backend │ source_url: null, 21:21:37 │ web-backend │ subtotal_price: '393.00', 21:21:37 │ web-backend │ subtotal_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '393.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '393.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ tags: '', 21:21:37 │ web-backend │ tax_exempt: false, 21:21:37 │ web-backend │ tax_lines: [], 21:21:37 │ web-backend │ taxes_included: false, 21:21:37 │ web-backend │ test: true, 21:21:37 │ web-backend │ token: '123456abcd', 21:21:37 │ web-backend │ total_discounts: '5.00', 21:21:37 │ web-backend │ total_discounts_set: { 21:21:37 │ web-backend │ shop_money: { amount: '5.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '5.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ total_line_items_price: '398.00', 21:21:37 │ web-backend │ total_line_items_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '398.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '398.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ total_outstanding: '398.00', 21:21:37 │ web-backend │ total_price: '403.00', 21:21:37 │ web-backend │ total_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '403.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '403.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ total_shipping_price_set: { 21:21:37 │ web-backend │ shop_money: { amount: '10.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '10.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ total_tax: '0.00', 21:21:37 │ web-backend │ total_tax_set: { 21:21:37 │ web-backend │ shop_money: { amount: '0.00', currency_code: 'USD' }, 21:21:37 │ web-backend │ presentment_money: { amount: '0.00', currency_code: 'USD' }
21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ total_tip_received: '0.00', 21:21:37 │ web-backend │ total_weight: 0, 21:21:37 │ web-backend │ updated_at: '2021-12-31T19:00:00-05:00', 21:21:37 │ web-backend │ user_id: null, 21:21:37 │ web-backend │ billing_address: { 21:21:37 │ web-backend │ first_name: 'Steve', 21:21:37 │ web-backend │ address1: '123 Shipping Street', 21:21:37 │ web-backend │ phone: '555-555-SHIP', 21:21:37 │ web-backend │ city: 'Shippington', 21:21:37 │ web-backend │ zip: '40003', 21:21:37 │ web-backend │ province: 'Kentucky', 21:21:37 │ web-backend │ country: 'United States', 21:21:37 │ web-backend │ last_name: 'Shipper', 21:21:37 │ web-backend │ address2: null, 21:21:37 │ web-backend │ company: 'Shipping Company', 21:21:37 │ web-backend │ latitude: null, 21:21:37 │ web-backend │ longitude: null, 21:21:37 │ web-backend │ name: 'Steve Shipper', 21:21:37 │ web-backend │ country_code: 'US', 21:21:37 │ web-backend │ province_code: 'KY' 21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ customer: { 21:21:37 │ web-backend │ id: 115310627314723950, 21:21:37 │ web-backend │ email: 'john@example.com', 21:21:37 │ web-backend │ accepts_marketing: false, 21:21:37 │ web-backend │ created_at: null, 21:21:37 │ web-backend │ updated_at: null, 21:21:37 │ web-backend │ first_name: 'John', 21:21:37 │ web-backend │ last_name: 'Smith', 21:21:37 │ web-backend │ state: 'disabled', 21:21:37 │ web-backend │ note: null, 21:21:37 │ web-backend │ verified_email: true, 21:21:37 │ web-backend │ multipass_identifier: null, 21:21:37 │ web-backend │ tax_exempt: false, 21:21:37 │ web-backend │ phone: null, 21:21:37 │ web-backend │ email_marketing_consent: { 21:21:37 │ web-backend │ state: 'not_subscribed', 21:21:37 │ web-backend │ opt_in_level: null, 21:21:37 │ web-backend │ consent_updated_at: null 21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ sms_marketing_consent: null, 21:21:37 │ web-backend │ tags: '', 21:21:37 │ web-backend │ currency: 'USD', 21:21:37 │ web-backend │ accepts_marketing_updated_at: null, 21:21:37 │ web-backend │ marketing_opt_in_level: null, 21:21:37 │ web-backend │ tax_exemptions: [], 21:21:37 │ web-backend │ admin_graphql_api_id: 'gid://shopify/Customer/115310627314723954', 21:21:37 │ web-backend │ default_address: { 21:21:37 │ web-backend │ id: 715243470612851200, 21:21:37 │ web-backend │ customer_id: 115310627314723950, 21:21:37 │ web-backend │ first_name: null, 21:21:37 │ web-backend │ last_name: null, 21:21:37 │ web-backend │ company: null, 21:21:37 │ web-backend │ address1: '123 Elm St.', 21:21:37 │ web-backend │ address2: null, 21:21:37 │ web-backend │ city: 'Ottawa', 21:21:37 │ web-backend │ province: 'Ontario', 21:21:37 │ web-backend │ country: 'Canada', 21:21:37 │ web-backend │ zip: 'K2H7A8', 21:21:37 │ web-backend │ phone: '123-123-1234', 21:21:37 │ web-backend │ name: '', 21:21:37 │ web-backend │ province_code: 'ON', 21:21:37 │ web-backend │ country_code: 'CA', 21:21:37 │ web-backend │ country_name: 'Canada', 21:21:37 │ web-backend │ default: true 21:21:37 │ web-backend │ } 21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ discount_applications: [], 21:21:37 │ web-backend │ fulfillments: [], 21:21:37 │ web-backend │ line_items: [ 21:21:37 │ web-backend │ { 21:21:37 │ web-backend │ id: 866550311766439000, 21:21:37 │ web-backend │ admin_graphql_api_id: 'gid://shopify/LineItem/866550311766439020', 21:21:37 │ web-backend │ attributed_staffs: [Array], 21:21:37 │ web-backend │ fulfillable_quantity: 1, 21:21:37 │ web-backend │ fulfillment_service: 'manual', 21:21:37 │ web-backend │ fulfillment_status: null, 21:21:37 │ web-backend │ gift_card: false, 21:21:37 │ web-backend │ grams: 567, 21:21:37 │ web-backend │ name: 'IPod Nano - 8GB', 21:21:37 │ web-backend │ price: '199.00', 21:21:37 │ web-backend │ price_set: [Object], 21:21:37 │ web-backend │ product_exists: true, 21:21:37 │ web-backend │ product_id: 632910392, 21:21:37 │ web-backend │ properties: [], 21:21:37 │ web-backend │ quantity: 1, 21:21:37 │ web-backend │ requires_shipping: true, 21:21:37 │ web-backend │ sku: 'IPOD2008PINK', 21:21:37 │ web-backend │ taxable: true, 21:21:37 │ web-backend │ title: 'IPod Nano - 8GB', 21:21:37 │ web-backend │ total_discount: '0.00', 21:21:37 │ web-backend │ total_discount_set: [Object], 21:21:37 │ web-backend │ variant_id: 808950810, 21:21:37 │ web-backend │ variant_inventory_management: 'shopify', 21:21:37 │ web-backend │ variant_title: null, 21:21:37 │ web-backend │ vendor: null, 21:21:37 │ web-backend │ tax_lines: [], 21:21:37 │ web-backend │ duties: [], 21:21:37 │ web-backend │ discount_allocations: [] 21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ { 21:21:37 │ web-backend │ id: 141249953214522980, 21:21:37 │ web-backend │ admin_graphql_api_id: 'gid://shopify/LineItem/141249953214522974', 21:21:37 │ web-backend │ attributed_staffs: [], 21:21:37 │ web-backend │ fulfillable_quantity: 1, 21:21:37 │ web-backend │ fulfillment_service: 'manual', 21:21:37 │ web-backend │ fulfillment_status: null, 21:21:37 │ web-backend │ gift_card: false, 21:21:37 │ web-backend │ grams: 567, 21:21:37 │ web-backend │ name: 'IPod Nano - 8GB', 21:21:37 │ web-backend │ price: '199.00', 21:21:37 │ web-backend │ price_set: [Object], 21:21:37 │ web-backend │ product_exists: true, 21:21:37 │ web-backend │ product_id: 632910392, 21:21:37 │ web-backend │ properties: [], 21:21:37 │ web-backend │ quantity: 1, 21:21:37 │ web-backend │ requires_shipping: true, 21:21:37 │ web-backend │ sku: 'IPOD2008PINK', 21:21:37 │ web-backend │ taxable: true, 21:21:37 │ web-backend │ title: 'IPod Nano - 8GB', 21:21:37 │ web-backend │ total_discount: '0.00', 21:21:37 │ web-backend │ total_discount_set: [Object], 21:21:37 │ web-backend │ variant_id: 808950810, 21:21:37 │ web-backend │ variant_inventory_management: 'shopify', 21:21:37 │ web-backend │ variant_title: null, 21:21:37 │ web-backend │ vendor: null, 21:21:37 │ web-backend │ tax_lines: [], 21:21:37 │ web-backend │ duties: [], 21:21:37 │ web-backend │ discount_allocations: [] 21:21:37 │ web-backend │ } 21:21:37 │ web-backend │ ], 21:21:37 │ web-backend │ payment_terms: null, 21:21:37 │ web-backend │ refunds: [], 21:21:37 │ web-backend │ shipping_address: { 21:21:37 │ web-backend │ first_name: 'Steve', 21:21:37 │ web-backend │ address1: '123 Shipping Street', 21:21:37 │ web-backend │ phone: '555-555-SHIP', 21:21:37 │ web-backend │ city: 'Shippington', 21:21:37 │ web-backend │ zip: '40003', 21:21:37 │ web-backend │ province: 'Kentucky', 21:21:37 │ web-backend │ country: 'United States', 21:21:37 │ web-backend │ last_name: 'Shipper', 21:21:37 │ web-backend │ address2: null, 21:21:37 │ web-backend │ company: 'Shipping Company', 21:21:37 │ web-backend │ latitude: null, 21:21:37 │ web-backend │ longitude: null, 21:21:37 │ web-backend │ name: 'Steve Shipper', 21:21:37 │ web-backend │ country_code: 'US', 21:21:37 │ web-backend │ province_code: 'KY' 21:21:37 │ web-backend │ }, 21:21:37 │ web-backend │ shipping_lines: [ 21:21:37 │ web-backend │ { 21:21:37 │ web-backend │ id: 271878346596884000, 21:21:37 │ web-backend │ carrier_identifier: null, 21:21:37 │ web-backend │ code: null, 21:21:37 │ web-backend │ discounted_price: '10.00', 21:21:37 │ web-backend │ discounted_price_set: [Object], 21:21:37 │ web-backend │ phone: null, 21:21:37 │ web-backend │ price: '10.00', 21:21:37 │ web-backend │ price_set: [Object], 21:21:37 │ web-backend │ requested_fulfillment_service_id: null, 21:21:37 │ web-backend │ source: 'shopify', 21:21:37 │ web-backend │ title: 'Generic Shipping', 21:21:37 │ web-backend │ tax_lines: [], 21:21:37 │ web-backend │ discount_allocations: [] 21:21:37 │ web-backend │ } 21:21:37 │ web-backend │ ] 21:21:37 │ web-backend │ } 21:21:37 │ web-backend │ --- /ORDER CREATE --- 21:21:37 │ web-backend │ [shopify-app/INFO] Webhook processed, returned status code 200 21:21:52 │ web-backend │ [shopify-app/INFO] Running validateAuthenticatedSession 21:21:52 │ web-backend │ [shopify-api/ERROR] Missing Authorization header, was the request made with authenticatedFetch? | {isOnline: false} 21:21:52 │ web-backend │ [shopify-app/INFO] Session was not valid. Redirecting to /api/auth?shop=undefined | {shop: undefined}

Reproduction steps

  1. Setup Shopify CLI App using npm init @shopify/app@latest --template node
  2. Setup Endpoint in App
  3. Call endpoint from StoreFront.

Operating System

Windows 10

Shopify CLI version (check your project's package.json if you're not sure)

3.48.1

Shell

Terminal

Node version (run node -v if you're not sure)

v18.17.1

What language and version are you using in your application?

No response

github-actions[bot] commented 1 year ago

This issue seems inactive. If it's still relevant, please add a comment saying so. Otherwise, take no action. → If there's no activity within a week, then a bot will automatically close this. Thanks for helping to improve Shopify's dev tooling and experience.

P.S. You can learn more about why we stale issues here.