shopify-app-js 0.0.1-security → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of shopify-app-js might be problematic. Click here for more details.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.changeset/flat-clouds-camp.md +5 -0
- package/.eslintrc.js +36 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/ISSUE_TEMPLATE/BUG_REPORT.md +36 -0
- package/.github/ISSUE_TEMPLATE/ENHANCEMENT.md +9 -0
- package/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +9 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +34 -0
- package/.github/dependabot.yml +9 -0
- package/.github/workflows/changelog.yml +30 -0
- package/.github/workflows/ci.yml +22 -0
- package/.github/workflows/cla.yml +22 -0
- package/.github/workflows/close-waiting-for-response-issues.yml +20 -0
- package/.github/workflows/main-release.yml +36 -0
- package/.github/workflows/markdown_link_check.yml +14 -0
- package/.github/workflows/markdown_link_checker_config.json +9 -0
- package/.github/workflows/publish-experimental-build.yml +30 -0
- package/.github/workflows/release-candidate.yml +35 -0
- package/.github/workflows/remove-labels-on-activity.yml +16 -0
- package/.github/workflows/stale.yml +26 -0
- package/.prettierignore +5 -0
- package/.prettierrc +1 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/CONTRIBUTING.md +39 -0
- package/LICENSE.md +9 -0
- package/README.md +62 -3
- package/RELEASING.md +142 -0
- package/loom.config.ts +115 -0
- package/package.json +44 -3
- package/packages/.prettierrc +1 -0
- package/packages/shopify-app-express/CHANGELOG.md +316 -0
- package/packages/shopify-app-express/LICENSE.md +9 -0
- package/packages/shopify-app-express/README.md +93 -0
- package/packages/shopify-app-express/docs/reference/README.md +3 -0
- package/packages/shopify-app-express/docs/reference/auth.md +76 -0
- package/packages/shopify-app-express/docs/reference/cspHeaders.md +24 -0
- package/packages/shopify-app-express/docs/reference/ensureInstalledOnShop.md +17 -0
- package/packages/shopify-app-express/docs/reference/migrating-app-v6-api-lib-to-express-lib.md +345 -0
- package/packages/shopify-app-express/docs/reference/processWebhooks.md +67 -0
- package/packages/shopify-app-express/docs/reference/redirectOutOfApp.md +77 -0
- package/packages/shopify-app-express/docs/reference/redirectToShopifyOrAppRoot.md +20 -0
- package/packages/shopify-app-express/docs/reference/shopifyApp.md +148 -0
- package/packages/shopify-app-express/docs/reference/validateAuthenticatedSession.md +30 -0
- package/packages/shopify-app-express/loom.config.ts +27 -0
- package/packages/shopify-app-express/package.json +54 -0
- package/packages/shopify-app-express/src/__tests__/index.test.ts +100 -0
- package/packages/shopify-app-express/src/__tests__/integration/oauth.test.ts +445 -0
- package/packages/shopify-app-express/src/__tests__/integration/responses.ts +135 -0
- package/packages/shopify-app-express/src/__tests__/integration/types.ts +22 -0
- package/packages/shopify-app-express/src/__tests__/integration/utils.ts +68 -0
- package/packages/shopify-app-express/src/__tests__/integration/webhooks.test.ts +208 -0
- package/packages/shopify-app-express/src/__tests__/redirect-to-auth.test.ts +103 -0
- package/packages/shopify-app-express/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-express/src/__tests__/test-helper.ts +204 -0
- package/packages/shopify-app-express/src/app-installations.ts +42 -0
- package/packages/shopify-app-express/src/auth/__tests__/auth.test.ts +303 -0
- package/packages/shopify-app-express/src/auth/auth-callback.ts +131 -0
- package/packages/shopify-app-express/src/auth/index.ts +32 -0
- package/packages/shopify-app-express/src/auth/types.ts +13 -0
- package/packages/shopify-app-express/src/config-types.ts +38 -0
- package/packages/shopify-app-express/src/error.ts +8 -0
- package/packages/shopify-app-express/src/index.ts +171 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/csp-headers.test.ts +69 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/ensure-installed-on-shop.test.ts +193 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/redirect-to-shopify-or-app-root.test.ts +59 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/validate-authenticated-session.test.ts +319 -0
- package/packages/shopify-app-express/src/middlewares/csp-headers.ts +31 -0
- package/packages/shopify-app-express/src/middlewares/ensure-installed-on-shop.ts +176 -0
- package/packages/shopify-app-express/src/middlewares/has-valid-access-token.ts +25 -0
- package/packages/shopify-app-express/src/middlewares/index.ts +15 -0
- package/packages/shopify-app-express/src/middlewares/redirect-to-shopify-or-app-root.ts +39 -0
- package/packages/shopify-app-express/src/middlewares/types.ts +6 -0
- package/packages/shopify-app-express/src/middlewares/validate-authenticated-session.ts +142 -0
- package/packages/shopify-app-express/src/redirect-out-of-app.ts +80 -0
- package/packages/shopify-app-express/src/redirect-to-auth.ts +70 -0
- package/packages/shopify-app-express/src/types.ts +26 -0
- package/packages/shopify-app-express/src/version.ts +1 -0
- package/packages/shopify-app-express/src/webhooks/__tests__/process.test.ts +138 -0
- package/packages/shopify-app-express/src/webhooks/index.ts +54 -0
- package/packages/shopify-app-express/src/webhooks/process.ts +22 -0
- package/packages/shopify-app-express/src/webhooks/types.ts +24 -0
- package/packages/shopify-app-express/tsconfig.json +10 -0
- package/packages/shopify-app-remix/.eslintrc.js +3 -0
- package/packages/shopify-app-remix/CHANGELOG.md +569 -0
- package/packages/shopify-app-remix/LICENSE.md +9 -0
- package/packages/shopify-app-remix/README.md +223 -0
- package/packages/shopify-app-remix/docs/build-docs.sh +11 -0
- package/packages/shopify-app-remix/docs/generated/generated_docs_data.json +18650 -0
- package/packages/shopify-app-remix/docs/generated/generated_static_pages.json +540 -0
- package/packages/shopify-app-remix/docs/staticPages/admin.doc.ts +130 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/auth-cors.example.tsx +11 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/auth.example.tsx +19 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/graphql.example.tsx +29 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/headers.example.tsx +10 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/rest-resources.example.tsx +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/rest.example.tsx +17 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/future-flags/config.example.ts +8 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/future-flags/unstable.example.ts +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/.graphqlrc.ts +16 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.npm.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.pnpm.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.yarn.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/package.json +5 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/webhooks/config.example.ts +19 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/webhooks/endpoint.example.ts +24 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/app-provider.example.ts +30 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/boundaries.example.ts +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/embedded-app-auth-strategy-config.example.ts +10 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/entry-server.example.ts +12 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/shopify-app.example.ts +14 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/splat-route.example.ts +11 -0
- package/packages/shopify-app-remix/docs/staticPages/future-flags.doc.ts +94 -0
- package/packages/shopify-app-remix/docs/staticPages/graphql-types.doc.ts +148 -0
- package/packages/shopify-app-remix/docs/staticPages/index.doc.ts +227 -0
- package/packages/shopify-app-remix/docs/staticPages/webhooks.doc.ts +64 -0
- package/packages/shopify-app-remix/docs/tsconfig.docs.json +9 -0
- package/packages/shopify-app-remix/docs/typeOverride.json +1 -0
- package/packages/shopify-app-remix/docs/upcoming_changes.md +153 -0
- package/packages/shopify-app-remix/loom.config.ts +57 -0
- package/packages/shopify-app-remix/package.json +93 -0
- package/packages/shopify-app-remix/src/react/.eslintrc.js +16 -0
- package/packages/shopify-app-remix/src/react/__tests__/test-helper.ts +22 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/AppProvider.doc.ts +34 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/AppProvider.tsx +121 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/__tests__/AppProvider.test.tsx +68 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/index.ts +1 -0
- package/packages/shopify-app-remix/src/react/components/RemixPolarisLink.tsx +14 -0
- package/packages/shopify-app-remix/src/react/components/index.ts +1 -0
- package/packages/shopify-app-remix/src/react/const.ts +2 -0
- package/packages/shopify-app-remix/src/react/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/.eslintrc.js +16 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/__tests__/request-mock.test.ts +171 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/const.ts +11 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-admin-api-client.ts +119 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-begin-auth-redirect.ts +22 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-document-request-headers.ts +25 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-exit-iframe.ts +37 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-login-redirect.ts +8 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-storefront-api-client.ts +50 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-hmac.ts +10 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-jwt.ts +31 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-thrown-response.ts +17 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/index.ts +14 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/request-mock.ts +169 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/setup-valid-session.ts +45 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/sign-request-cookie.ts +21 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/test-config.ts +112 -0
- package/packages/shopify-app-remix/src/server/__tests__/override-logger.test.ts +101 -0
- package/packages/shopify-app-remix/src/server/__tests__/shopify-app.test.ts +119 -0
- package/packages/shopify-app-remix/src/server/adapters/__tests__/node-app-bridge-url.test.ts +18 -0
- package/packages/shopify-app-remix/src/server/adapters/__tests__/node.test.ts +28 -0
- package/packages/shopify-app-remix/src/server/adapters/node/__tests__/setup-jest.ts +10 -0
- package/packages/shopify-app-remix/src/server/adapters/node/index.ts +20 -0
- package/packages/shopify-app-remix/src/server/adapters/vercel/__tests__/setup-jest.ts +12 -0
- package/packages/shopify-app-remix/src/server/adapters/vercel/index.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/admin-client.test.ts +181 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/doc-request-path.test.ts +151 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/exit-i-frame-path.test.ts +99 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/patch-session-token-path.test.ts +58 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/reject-bot.test.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/respond-to-options.test.ts +50 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/session-token-header-path.test.ts +91 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/authenticate.admin.doc.ts +37 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/authenticate.ts +201 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/cancel.test.ts +258 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/check.test.ts +254 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/mock-responses.ts +65 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/request.test.ts +373 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/require.test.ts +316 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/authenticate.admin.billing.doc.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/cancel.ts +37 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/check.ts +38 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/index.ts +4 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/request.ts +101 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/require.ts +56 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/types.ts +383 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/__tests__/redirect.test.ts +313 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/__tests__/validate-redirect-url.test.ts +84 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/begin-auth.ts +17 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/create-admin-api-context.ts +22 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/ensure-app-is-embedded-if-required.ts +18 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/ensure-session-token-search-param-if-required.ts +25 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/handle-client-error.ts +43 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/index.ts +14 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-auth-page.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-bounce-page.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-shopify-or-app-root.ts +21 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-with-app-bridge-headers.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-with-exitiframe.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect.ts +83 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/render-app-bridge.ts +46 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/trigger-after-auth-hook.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/validate-redirect-url.ts +67 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/validate-shop-and-host-params.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/admin-client.test.ts +222 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/auth-callback-path.test.ts +395 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/auth-path.test.ts +83 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/authenticate.test.ts +183 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/ensure-installed-on-shop.test.ts +234 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/session-token-header-path.test.ts +79 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/token-exchange/admin-client.test.ts +189 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/token-exchange/authenticate.test.ts +310 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/auth-code-flow.ts +333 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/token-exchange.ts +169 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/types.ts +29 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/types.ts +199 -0
- package/packages/shopify-app-remix/src/server/authenticate/const.ts +15 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/__tests__/authenticate.test.ts +142 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/authenticate.flow.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/authenticate.ts +71 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/types.ts +90 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/add-response-headers.test.ts +25 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/app-bridge-url.test.ts +21 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/idempotent-promise-handler.test.ts +104 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/add-response-headers.ts +43 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/app-bridge-url.ts +10 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/ensure-cors-headers.ts +38 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/get-session-token-header.ts +11 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/idempotent-promise-handler.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/index.ts +8 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/reject-bot-request.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/respond-to-invalid-session-token.ts +29 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/respond-to-options-request.ts +26 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/validate-session-token.ts +32 -0
- package/packages/shopify-app-remix/src/server/authenticate/login/__tests__/login.test.ts +157 -0
- package/packages/shopify-app-remix/src/server/authenticate/login/login.ts +53 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/__tests__/factory.test.ts +224 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/__tests__/authenticate.test.ts +282 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.ts +36 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/authenticate.ts +90 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/types.ts +164 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/__tests__/authenticate.test.ts +142 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/authenticate.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/types.ts +65 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/factory.ts +49 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/types.ts +77 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/authenticate.test.ts +207 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/mock-responses.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/register.test.ts +210 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/authenticate.ts +113 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/authenticate.webhooks.doc.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/register.ts +48 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/types.ts +246 -0
- package/packages/shopify-app-remix/src/server/boundary/__tests__/error.test.tsx +36 -0
- package/packages/shopify-app-remix/src/server/boundary/__tests__/headers.test.ts +66 -0
- package/packages/shopify-app-remix/src/server/boundary/error.tsx +14 -0
- package/packages/shopify-app-remix/src/server/boundary/headers.ts +15 -0
- package/packages/shopify-app-remix/src/server/boundary/index.ts +39 -0
- package/packages/shopify-app-remix/src/server/boundary/types.ts +4 -0
- package/packages/shopify-app-remix/src/server/clients/admin/authenticate.admin.api.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/clients/admin/factory.ts +30 -0
- package/packages/shopify-app-remix/src/server/clients/admin/graphql.ts +39 -0
- package/packages/shopify-app-remix/src/server/clients/admin/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/admin/rest.ts +157 -0
- package/packages/shopify-app-remix/src/server/clients/admin/types.ts +178 -0
- package/packages/shopify-app-remix/src/server/clients/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/authenticate.storefront.api.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/factory.ts +32 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/types.ts +31 -0
- package/packages/shopify-app-remix/src/server/clients/types.ts +27 -0
- package/packages/shopify-app-remix/src/server/config-types.ts +293 -0
- package/packages/shopify-app-remix/src/server/errors.ts +3 -0
- package/packages/shopify-app-remix/src/server/future/flags.ts +57 -0
- package/packages/shopify-app-remix/src/server/index.ts +20 -0
- package/packages/shopify-app-remix/src/server/override-logger.ts +42 -0
- package/packages/shopify-app-remix/src/server/shopify-app.doc.ts +45 -0
- package/packages/shopify-app-remix/src/server/shopify-app.ts +198 -0
- package/packages/shopify-app-remix/src/server/types.ts +509 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/__tests__/factory.test.ts +30 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/factory.ts +29 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/types.ts +117 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/unauthenticated.admin.doc.ts +40 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/helpers/get-offline-session.ts +13 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/helpers/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/__tests__/factory.test.ts +30 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/factory.ts +28 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/types.ts +39 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/unauthenticated.storefront.doc.ts +40 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/types.ts +68 -0
- package/packages/shopify-app-remix/src/server/version.ts +1 -0
- package/packages/shopify-app-remix/tsconfig.json +11 -0
- package/packages/shopify-app-session-storage/CHANGELOG.md +149 -0
- package/packages/shopify-app-session-storage/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage/README.md +5 -0
- package/packages/shopify-app-session-storage/implementing-session-storage.md +214 -0
- package/packages/shopify-app-session-storage/loom.config.ts +45 -0
- package/packages/shopify-app-session-storage/package.json +44 -0
- package/packages/shopify-app-session-storage/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage/src/abstract-migration-engine.ts +53 -0
- package/packages/shopify-app-session-storage/src/index.ts +3 -0
- package/packages/shopify-app-session-storage/src/rdbms-session-storage-migrator.ts +59 -0
- package/packages/shopify-app-session-storage/src/types.ts +174 -0
- package/packages/shopify-app-session-storage/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-dynamodb/CHANGELOG.md +150 -0
- package/packages/shopify-app-session-storage-dynamodb/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-dynamodb/README.md +75 -0
- package/packages/shopify-app-session-storage-dynamodb/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-dynamodb/package.json +51 -0
- package/packages/shopify-app-session-storage-dynamodb/src/__tests__/dynamodb.test.ts +93 -0
- package/packages/shopify-app-session-storage-dynamodb/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-dynamodb/src/dynamodb.ts +126 -0
- package/packages/shopify-app-session-storage-dynamodb/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-kv/CHANGELOG.md +204 -0
- package/packages/shopify-app-session-storage-kv/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-kv/README.md +41 -0
- package/packages/shopify-app-session-storage-kv/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-kv/package.json +52 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/kv-namespace-dummy-worker.ts +8 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/kv.test.ts +22 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-kv/src/kv.ts +87 -0
- package/packages/shopify-app-session-storage-kv/tsconfig.json +11 -0
- package/packages/shopify-app-session-storage-memory/CHANGELOG.md +190 -0
- package/packages/shopify-app-session-storage-memory/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-memory/README.md +19 -0
- package/packages/shopify-app-session-storage-memory/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-memory/package.json +46 -0
- package/packages/shopify-app-session-storage-memory/src/__tests__/memory.test.ts +12 -0
- package/packages/shopify-app-session-storage-memory/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-memory/src/memory.ts +34 -0
- package/packages/shopify-app-session-storage-memory/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-mongodb/CHANGELOG.md +208 -0
- package/packages/shopify-app-session-storage-mongodb/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-mongodb/README.md +30 -0
- package/packages/shopify-app-session-storage-mongodb/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-mongodb/package.json +49 -0
- package/packages/shopify-app-session-storage-mongodb/src/__tests__/mongodb.test.ts +54 -0
- package/packages/shopify-app-session-storage-mongodb/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-mongodb/src/mongodb.ts +120 -0
- package/packages/shopify-app-session-storage-mongodb/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-mysql/CHANGELOG.md +220 -0
- package/packages/shopify-app-session-storage-mysql/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-mysql/README.md +41 -0
- package/packages/shopify-app-session-storage-mysql/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-mysql/package.json +50 -0
- package/packages/shopify-app-session-storage-mysql/src/__tests__/mysql.test.ts +137 -0
- package/packages/shopify-app-session-storage-mysql/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-mysql/src/migrations.ts +18 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql-connection.ts +108 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql-migrator.ts +53 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql.ts +178 -0
- package/packages/shopify-app-session-storage-mysql/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-postgresql/CHANGELOG.md +210 -0
- package/packages/shopify-app-session-storage-postgresql/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-postgresql/README.md +39 -0
- package/packages/shopify-app-session-storage-postgresql/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-postgresql/package.json +52 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/migrate-to-case-sensitivity.test.ts +344 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/postgresql.test.ts +136 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-postgresql/src/migrations.ts +70 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgres-connection.ts +94 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgres-migrator.ts +27 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgresql.ts +178 -0
- package/packages/shopify-app-session-storage-postgresql/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-prisma/CHANGELOG.md +148 -0
- package/packages/shopify-app-session-storage-prisma/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-prisma/README.md +68 -0
- package/packages/shopify-app-session-storage-prisma/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-prisma/package.json +51 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/20230425184828_init/migration.sql +11 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/20230906155758_mySession/migration.sql +11 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/migration_lock.toml +3 -0
- package/packages/shopify-app-session-storage-prisma/prisma/schema.prisma +30 -0
- package/packages/shopify-app-session-storage-prisma/src/__tests__/prisma.test.ts +66 -0
- package/packages/shopify-app-session-storage-prisma/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-prisma/src/prisma.ts +145 -0
- package/packages/shopify-app-session-storage-prisma/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-redis/CHANGELOG.md +200 -0
- package/packages/shopify-app-session-storage-redis/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-redis/README.md +38 -0
- package/packages/shopify-app-session-storage-redis/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-redis/package.json +50 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/migration-test-data.ts +46 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/redis.conf +2 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/redis.test.ts +236 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-redis/src/migrations.ts +36 -0
- package/packages/shopify-app-session-storage-redis/src/redis-connection.ts +64 -0
- package/packages/shopify-app-session-storage-redis/src/redis-migrator.ts +58 -0
- package/packages/shopify-app-session-storage-redis/src/redis.ts +167 -0
- package/packages/shopify-app-session-storage-redis/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-sqlite/CHANGELOG.md +202 -0
- package/packages/shopify-app-session-storage-sqlite/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-sqlite/README.md +25 -0
- package/packages/shopify-app-session-storage-sqlite/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-sqlite/package.json +51 -0
- package/packages/shopify-app-session-storage-sqlite/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-sqlite/src/__tests__/sqlite.test.ts +44 -0
- package/packages/shopify-app-session-storage-sqlite/src/migrations.ts +54 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite-connection.ts +80 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite-migrator.ts +34 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite.ts +147 -0
- package/packages/shopify-app-session-storage-sqlite/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-test-utils/CHANGELOG.md +185 -0
- package/packages/shopify-app-session-storage-test-utils/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-test-utils/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-test-utils/package.json +48 -0
- package/packages/shopify-app-session-storage-test-utils/src/__tests__/session-test-utils.test.ts +273 -0
- package/packages/shopify-app-session-storage-test-utils/src/battery-of-tests.ts +250 -0
- package/packages/shopify-app-session-storage-test-utils/src/index.ts +2 -0
- package/packages/shopify-app-session-storage-test-utils/src/session-test-utils.ts +24 -0
- package/packages/shopify-app-session-storage-test-utils/src/utils.ts +71 -0
- package/packages/shopify-app-session-storage-test-utils/tsconfig.json +10 -0
- package/tests/setup/build.js +1 -0
- package/tests/setup/setup-jest.ts +8 -0
- package/tsconfig.base.json +41 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {Session, ShopifyRestResources} from '@shopify/shopify-api';
|
|
2
|
+
|
|
3
|
+
import {AdminApiContext, StorefrontContext} from '../../../clients';
|
|
4
|
+
|
|
5
|
+
export type AuthenticateAppProxy = (
|
|
6
|
+
request: Request,
|
|
7
|
+
) => Promise<AppProxyContext | AppProxyContextWithSession>;
|
|
8
|
+
|
|
9
|
+
interface Options {
|
|
10
|
+
/**
|
|
11
|
+
* Whether to use the shop's theme layout around the Liquid content.
|
|
12
|
+
*/
|
|
13
|
+
layout?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type LiquidResponseFunction = (
|
|
17
|
+
body: string,
|
|
18
|
+
initAndOptions?: number | (ResponseInit & Options),
|
|
19
|
+
) => Response;
|
|
20
|
+
|
|
21
|
+
interface Context {
|
|
22
|
+
/**
|
|
23
|
+
* A utility for creating a Liquid Response.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <caption>Rendering liquid content.</caption>
|
|
27
|
+
* <description>Use the `liquid` helper to render a `Response` with Liquid content using the shop's theme.</description>
|
|
28
|
+
* ```ts
|
|
29
|
+
* // app/routes/**\/.ts
|
|
30
|
+
* import {authenticate} from "~/shopify.server"
|
|
31
|
+
*
|
|
32
|
+
* export async function loader({ request }) {
|
|
33
|
+
* const {liquid} = await authenticate.public.appProxy(request);
|
|
34
|
+
*
|
|
35
|
+
* return liquid("Hello {{shop.name}}");
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* <caption>Rendering liquid content without a layout.</caption>
|
|
41
|
+
* <description>Set the `layout` option to `false` to render the Liquid content without a theme.</description>
|
|
42
|
+
* ```ts
|
|
43
|
+
* // app/routes/**\/.ts
|
|
44
|
+
* import {authenticate} from "~/shopify.server"
|
|
45
|
+
*
|
|
46
|
+
* export async function loader({ request }) {
|
|
47
|
+
* const {liquid} = await authenticate.public.appProxy(request);
|
|
48
|
+
*
|
|
49
|
+
* return liquid(
|
|
50
|
+
* "Hello {{shop.name}}",
|
|
51
|
+
* { layout: false }
|
|
52
|
+
* );
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
liquid: LiquidResponseFunction;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface AppProxyContext extends Context {
|
|
60
|
+
/**
|
|
61
|
+
* No session is available for the shop that made this request.
|
|
62
|
+
*
|
|
63
|
+
* This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice.
|
|
64
|
+
*/
|
|
65
|
+
session: undefined;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* No session is available for the shop that made this request.
|
|
69
|
+
* Therefore no methods for interacting with the GraphQL / REST Admin APIs are available.
|
|
70
|
+
*/
|
|
71
|
+
admin: undefined;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* No session is available for the shop that made this request.
|
|
75
|
+
* Therefore no method for interacting with the Storefront API is available.
|
|
76
|
+
*/
|
|
77
|
+
storefront: undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface AppProxyContextWithSession<
|
|
81
|
+
Resources extends ShopifyRestResources = ShopifyRestResources,
|
|
82
|
+
> extends Context {
|
|
83
|
+
/**
|
|
84
|
+
* The session for the shop that made the request.
|
|
85
|
+
*
|
|
86
|
+
* This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice.
|
|
87
|
+
*
|
|
88
|
+
* Use this to get shop or user-specific data.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* <caption>Using the session object.</caption>
|
|
92
|
+
* <description>Get the session for the shop that initiated the request to the app proxy.</description>
|
|
93
|
+
* ```ts
|
|
94
|
+
* // app/routes/**\/.ts
|
|
95
|
+
* import { json } from "@remix-run/node";
|
|
96
|
+
* import { authenticate } from "../shopify.server";
|
|
97
|
+
* import { getMyAppModelData } from "~/db/model.server";
|
|
98
|
+
*
|
|
99
|
+
* export const loader = async ({ request }) => {
|
|
100
|
+
* // Get the session for the shop that initiated the request to the app proxy.
|
|
101
|
+
* const { session } = await authenticate.public.appProxy(request);
|
|
102
|
+
*
|
|
103
|
+
* // Use the session data to make to queries to your database or additional requests.
|
|
104
|
+
* return json(await getMyAppModelData({shop: session.shop));
|
|
105
|
+
* };
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
session: Session;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Methods for interacting with the GraphQL / REST Admin APIs for the store that made the request.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* <caption>Interacting with the Admin API.</caption>
|
|
115
|
+
* <description>Use the `admin` object to interact with the REST or GraphQL APIs.</description>
|
|
116
|
+
* ```ts
|
|
117
|
+
* // app/routes/**\/.ts
|
|
118
|
+
* import { json } from "@remix-run/node";
|
|
119
|
+
* import { authenticate } from "../shopify.server";
|
|
120
|
+
*
|
|
121
|
+
* export async function action({ request }: ActionFunctionArgs) {
|
|
122
|
+
* const { admin } = await authenticate.public.appProxy(request);
|
|
123
|
+
*
|
|
124
|
+
* const response = await admin.graphql(
|
|
125
|
+
* `#graphql
|
|
126
|
+
* mutation populateProduct($input: ProductInput!) {
|
|
127
|
+
* productCreate(input: $input) {
|
|
128
|
+
* product {
|
|
129
|
+
* id
|
|
130
|
+
* }
|
|
131
|
+
* }
|
|
132
|
+
* }`,
|
|
133
|
+
* { variables: { input: { title: "Product Name" } } }
|
|
134
|
+
* );
|
|
135
|
+
*
|
|
136
|
+
* const productData = await response.json();
|
|
137
|
+
* return json({ data: productData.data });
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
admin: AdminApiContext<Resources>;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Method for interacting with the Shopify Storefront Graphql API for the store that made the request.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* <caption>Interacting with the Storefront API.</caption>
|
|
148
|
+
* <description>Use the `storefront` object to interact with the GraphQL API.</description>
|
|
149
|
+
* ```ts
|
|
150
|
+
* // app/routes/**\/.ts
|
|
151
|
+
* import { json } from "@remix-run/node";
|
|
152
|
+
* import { authenticate } from "../shopify.server";
|
|
153
|
+
*
|
|
154
|
+
* export async function action({ request }: ActionFunctionArgs) {
|
|
155
|
+
* const { storefront } = await authenticate.public.appProxy(request);
|
|
156
|
+
*
|
|
157
|
+
* const response = await storefront.graphql(`{blogs(first: 10) { edges { node { id } } } }`);
|
|
158
|
+
*
|
|
159
|
+
* return json(await response.json());
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
storefront: StorefrontContext;
|
|
164
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {shopifyApp} from '../../../..';
|
|
2
|
+
import {
|
|
3
|
+
APP_URL,
|
|
4
|
+
getJwt,
|
|
5
|
+
getThrownResponse,
|
|
6
|
+
testConfig,
|
|
7
|
+
} from '../../../../__test-helpers';
|
|
8
|
+
|
|
9
|
+
describe('JWT validation', () => {
|
|
10
|
+
it('returns token when successful', async () => {
|
|
11
|
+
// GIVEN
|
|
12
|
+
const shopify = shopifyApp(testConfig());
|
|
13
|
+
const {token, payload} = getJwt();
|
|
14
|
+
|
|
15
|
+
// WHEN
|
|
16
|
+
const {sessionToken} = await shopify.authenticate.public.checkout(
|
|
17
|
+
new Request(APP_URL, {
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${token}`,
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// THEN
|
|
25
|
+
expect(sessionToken).toMatchObject(payload);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('sets extra CORS allowed headers when requested from a different origin', async () => {
|
|
29
|
+
// GIVEN
|
|
30
|
+
const shopify = shopifyApp(testConfig());
|
|
31
|
+
const {token} = getJwt();
|
|
32
|
+
|
|
33
|
+
// WHEN
|
|
34
|
+
const {cors} = await shopify.authenticate.public.checkout(
|
|
35
|
+
new Request(APP_URL, {
|
|
36
|
+
headers: {
|
|
37
|
+
Origin: 'https://some-other.origin',
|
|
38
|
+
Authorization: `Bearer ${token}`,
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
{corsHeaders: ['Content-Type', 'X-Extra-Header']},
|
|
42
|
+
);
|
|
43
|
+
const response = cors(new Response());
|
|
44
|
+
|
|
45
|
+
// THEN
|
|
46
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
47
|
+
'Authorization, Content-Type, X-Extra-Header',
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('responds to preflight requests', async () => {
|
|
52
|
+
// GIVEN
|
|
53
|
+
const shopify = shopifyApp(testConfig());
|
|
54
|
+
const {token, payload} = getJwt();
|
|
55
|
+
|
|
56
|
+
// WHEN
|
|
57
|
+
const response = await getThrownResponse(
|
|
58
|
+
async (request) => shopify.authenticate.public.checkout(request),
|
|
59
|
+
new Request(APP_URL, {
|
|
60
|
+
method: 'OPTIONS',
|
|
61
|
+
headers: {Authorization: `Bearer ${token}`},
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// THEN
|
|
66
|
+
expect(response.status).toBe(204);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('responds to preflight requests from a different origin with extra CORS allowed headers', async () => {
|
|
70
|
+
// GIVEN
|
|
71
|
+
const shopify = shopifyApp(testConfig());
|
|
72
|
+
const {token} = getJwt();
|
|
73
|
+
const request = new Request(APP_URL, {
|
|
74
|
+
method: 'OPTIONS',
|
|
75
|
+
headers: {
|
|
76
|
+
Origin: 'https://some-other.origin',
|
|
77
|
+
Authorization: `Bearer ${token}`,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// WHEN
|
|
82
|
+
const response = await getThrownResponse(
|
|
83
|
+
async (request) =>
|
|
84
|
+
shopify.authenticate.public.checkout(request, {
|
|
85
|
+
corsHeaders: ['X-Extra-Header'],
|
|
86
|
+
}),
|
|
87
|
+
request,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// THEN
|
|
91
|
+
expect(response.status).toBe(204);
|
|
92
|
+
expect(response.headers.get('Access-Control-Allow-Headers')).toBe(
|
|
93
|
+
'Authorization, Content-Type, X-Extra-Header',
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('throws a 401 on missing Authorization bearer token', async () => {
|
|
98
|
+
// GIVEN
|
|
99
|
+
const shopify = shopifyApp(testConfig());
|
|
100
|
+
|
|
101
|
+
// WHEN
|
|
102
|
+
const response = await getThrownResponse(
|
|
103
|
+
async (request) => shopify.authenticate.public.checkout(request),
|
|
104
|
+
new Request(APP_URL),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// THEN
|
|
108
|
+
expect(response.status).toBe(401);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('throws a 401 on invalid Authorization bearer token', async () => {
|
|
112
|
+
// GIVEN
|
|
113
|
+
const shopify = shopifyApp(testConfig());
|
|
114
|
+
|
|
115
|
+
// WHEN
|
|
116
|
+
const response = await getThrownResponse(
|
|
117
|
+
async (request) => shopify.authenticate.public.checkout(request),
|
|
118
|
+
new Request(APP_URL, {
|
|
119
|
+
headers: {Authorization: `Bearer this_is_not_a_valid_token`},
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// THEN
|
|
124
|
+
expect(response.status).toBe(401);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('rejects bot requests', async () => {
|
|
128
|
+
// GIVEN
|
|
129
|
+
const shopify = shopifyApp(testConfig());
|
|
130
|
+
|
|
131
|
+
// WHEN
|
|
132
|
+
const response = await getThrownResponse(
|
|
133
|
+
async (request) => shopify.authenticate.public.checkout(request),
|
|
134
|
+
new Request(APP_URL, {
|
|
135
|
+
headers: {'User-Agent': 'Googlebot'},
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// THEN
|
|
140
|
+
expect(response.status).toBe(410);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs';
|
|
2
|
+
|
|
3
|
+
const data: ReferenceEntityTemplateSchema = {
|
|
4
|
+
name: 'Checkout',
|
|
5
|
+
description:
|
|
6
|
+
'The `authenticate.public.checkout` function ensures that checkout extension requests are coming from Shopify, and returns helpers to respond with the correct headers.',
|
|
7
|
+
category: 'Authenticate',
|
|
8
|
+
subCategory: 'Public',
|
|
9
|
+
type: 'object',
|
|
10
|
+
isVisualComponent: false,
|
|
11
|
+
definitions: [
|
|
12
|
+
{
|
|
13
|
+
title: 'authenticate.public.checkout',
|
|
14
|
+
description:
|
|
15
|
+
'Authenticates requests coming from Shopify checkout extensions.',
|
|
16
|
+
type: 'AuthenticateCheckout',
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
jsDocTypeExamples: ['CheckoutContext'],
|
|
20
|
+
related: [],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default data;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type {BasicParams} from '../../../types';
|
|
2
|
+
import {
|
|
3
|
+
ensureCORSHeadersFactory,
|
|
4
|
+
getSessionTokenHeader,
|
|
5
|
+
respondToBotRequest,
|
|
6
|
+
respondToOptionsRequest,
|
|
7
|
+
validateSessionToken,
|
|
8
|
+
} from '../../helpers';
|
|
9
|
+
|
|
10
|
+
import type {AuthenticateCheckout, CheckoutContext} from './types';
|
|
11
|
+
|
|
12
|
+
export function authenticateCheckoutFactory(
|
|
13
|
+
params: BasicParams,
|
|
14
|
+
): AuthenticateCheckout {
|
|
15
|
+
return async function authenticateCheckout(
|
|
16
|
+
request,
|
|
17
|
+
options = {},
|
|
18
|
+
): Promise<CheckoutContext> {
|
|
19
|
+
const {logger} = params;
|
|
20
|
+
|
|
21
|
+
const corsHeaders = options.corsHeaders ?? [];
|
|
22
|
+
|
|
23
|
+
respondToBotRequest(params, request);
|
|
24
|
+
respondToOptionsRequest(params, request, corsHeaders);
|
|
25
|
+
|
|
26
|
+
const sessionTokenHeader = getSessionTokenHeader(request);
|
|
27
|
+
|
|
28
|
+
logger.info('Authenticating checkout request');
|
|
29
|
+
|
|
30
|
+
if (!sessionTokenHeader) {
|
|
31
|
+
logger.debug('Request did not contain a session token');
|
|
32
|
+
throw new Response(undefined, {
|
|
33
|
+
status: 401,
|
|
34
|
+
statusText: 'Unauthorized',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
sessionToken: await validateSessionToken(params, sessionTokenHeader, {
|
|
40
|
+
checkAudience: false,
|
|
41
|
+
}),
|
|
42
|
+
cors: ensureCORSHeadersFactory(params, request, corsHeaders),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {JwtPayload} from '@shopify/shopify-api';
|
|
2
|
+
|
|
3
|
+
import {EnsureCORSFunction} from '../../helpers/ensure-cors-headers';
|
|
4
|
+
|
|
5
|
+
export type AuthenticateCheckout = (
|
|
6
|
+
request: Request,
|
|
7
|
+
options?: AuthenticateCheckoutOptions,
|
|
8
|
+
) => Promise<CheckoutContext>;
|
|
9
|
+
|
|
10
|
+
export interface AuthenticateCheckoutOptions {
|
|
11
|
+
corsHeaders?: string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Authenticated Context for a checkout request
|
|
16
|
+
*/
|
|
17
|
+
export interface CheckoutContext {
|
|
18
|
+
/**
|
|
19
|
+
* The decoded and validated session token for the request
|
|
20
|
+
*
|
|
21
|
+
* Refer to the OAuth docs for the [session token payload](https://shopify.dev/docs/apps/auth/oauth/session-tokens#payload).
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <caption>Using the decoded session token.</caption>
|
|
25
|
+
* <description>Get store-specific data using the `sessionToken` object.</description>
|
|
26
|
+
* ```ts
|
|
27
|
+
* // app/routes/public/my-route.ts
|
|
28
|
+
* import { LoaderFunctionArgs, json } from "@remix-run/node";
|
|
29
|
+
* import { authenticate } from "../shopify.server";
|
|
30
|
+
* import { getMyAppData } from "~/db/model.server";
|
|
31
|
+
*
|
|
32
|
+
* export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|
33
|
+
* const { sessionToken } = await authenticate.public.checkout(
|
|
34
|
+
* request
|
|
35
|
+
* );
|
|
36
|
+
* return json(await getMyAppData({shop: sessionToken.dest}));
|
|
37
|
+
* };
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
sessionToken: JwtPayload;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A function that ensures the CORS headers are set correctly for the response.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <caption>Setting CORS headers for a public request.</caption>
|
|
47
|
+
* <description>Use the `cors` helper to ensure your app can respond to checkout extension requests.</description>
|
|
48
|
+
* ```ts
|
|
49
|
+
* // app/routes/public/my-route.ts
|
|
50
|
+
* import { LoaderFunctionArgs, json } from "@remix-run/node";
|
|
51
|
+
* import { authenticate } from "../shopify.server";
|
|
52
|
+
* import { getMyAppData } from "~/db/model.server";
|
|
53
|
+
*
|
|
54
|
+
* export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|
55
|
+
* const { sessionToken, cors } = await authenticate.public.checkout(
|
|
56
|
+
* request,
|
|
57
|
+
* { corsHeaders: ["X-My-Custom-Header"] }
|
|
58
|
+
* );
|
|
59
|
+
* const data = await getMyAppData({shop: sessionToken.dest});
|
|
60
|
+
* return cors(json(data));
|
|
61
|
+
* };
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
cors: EnsureCORSFunction;
|
|
65
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {ShopifyRestResources} from '@shopify/shopify-api';
|
|
2
|
+
|
|
3
|
+
import {BasicParams} from '../../types';
|
|
4
|
+
import {FutureFlagOptions} from '../../future/flags';
|
|
5
|
+
|
|
6
|
+
import {authenticateCheckoutFactory} from './checkout/authenticate';
|
|
7
|
+
import {AuthenticateCheckoutOptions} from './checkout/types';
|
|
8
|
+
import {authenticateAppProxyFactory} from './appProxy/authenticate';
|
|
9
|
+
import {
|
|
10
|
+
AuthenticatePublic,
|
|
11
|
+
AuthenticatePublicLegacy,
|
|
12
|
+
AuthenticatePublicObject,
|
|
13
|
+
} from './types';
|
|
14
|
+
|
|
15
|
+
export function authenticatePublicFactory<
|
|
16
|
+
Future extends FutureFlagOptions,
|
|
17
|
+
Resources extends ShopifyRestResources,
|
|
18
|
+
>(params: BasicParams): AuthenticatePublic<Future> {
|
|
19
|
+
const {logger, config} = params;
|
|
20
|
+
|
|
21
|
+
const authenticateCheckout = authenticateCheckoutFactory(params);
|
|
22
|
+
const authenticateAppProxy = authenticateAppProxyFactory<Resources>(params);
|
|
23
|
+
|
|
24
|
+
if (config.future.v3_authenticatePublic) {
|
|
25
|
+
const context: AuthenticatePublicObject = {
|
|
26
|
+
checkout: authenticateCheckout,
|
|
27
|
+
appProxy: authenticateAppProxy,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return context as AuthenticatePublic<Future>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const authenticatePublic: AuthenticatePublicLegacy = (
|
|
34
|
+
request: Request,
|
|
35
|
+
options: AuthenticateCheckoutOptions,
|
|
36
|
+
) => {
|
|
37
|
+
logger.deprecated(
|
|
38
|
+
'3.0.0',
|
|
39
|
+
'authenticate.public() will be deprecated in v3. Use authenticate.public.checkout() instead.',
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return authenticateCheckout(request, options);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
authenticatePublic.checkout = authenticateCheckout;
|
|
46
|
+
authenticatePublic.appProxy = authenticateAppProxy;
|
|
47
|
+
|
|
48
|
+
return authenticatePublic;
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './factory';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {FeatureEnabled, FutureFlagOptions} from '../../future/flags';
|
|
2
|
+
|
|
3
|
+
import type {AuthenticateCheckout} from './checkout/types';
|
|
4
|
+
import type {AuthenticateAppProxy} from './appProxy/types';
|
|
5
|
+
|
|
6
|
+
// Eventually this will be just the `{}` bit without `AuthenticateCheckout &`
|
|
7
|
+
// We have this is because in v1 public WAS the only public authenticate method
|
|
8
|
+
// But it became tightly coupled to authentictaing Checkout requests.
|
|
9
|
+
// In V2 you will have only public.checkout() and public.appProxy(), no public()
|
|
10
|
+
|
|
11
|
+
export interface AuthenticatePublicObject {
|
|
12
|
+
/**
|
|
13
|
+
* Authenticate a request from a checkout extension
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <caption>Authenticating a checkout extension request</caption>
|
|
17
|
+
* ```ts
|
|
18
|
+
* // /app/routes/public/widgets.ts
|
|
19
|
+
* import { LoaderFunctionArgs, json } from "@remix-run/node";
|
|
20
|
+
* import { authenticate } from "../shopify.server";
|
|
21
|
+
*
|
|
22
|
+
* export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|
23
|
+
* const { sessionToken, cors } = await authenticate.public.checkout(
|
|
24
|
+
* request,
|
|
25
|
+
* );
|
|
26
|
+
* return cors(json({my: "data", shop: sessionToken.dest}));
|
|
27
|
+
* };
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
checkout: AuthenticateCheckout;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Authenticate a request from an app proxy
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* <caption>Authenticating an app proxy request</caption>
|
|
37
|
+
* ```ts
|
|
38
|
+
* // /app/routes/public/widgets.ts
|
|
39
|
+
* import { LoaderFunctionArgs, json } from "@remix-run/node";
|
|
40
|
+
* import { authenticate } from "../shopify.server";
|
|
41
|
+
*
|
|
42
|
+
* export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|
43
|
+
* await authenticate.public.appProxy(
|
|
44
|
+
* request,
|
|
45
|
+
* );
|
|
46
|
+
*
|
|
47
|
+
* const {searchParams} = new URL(request.url);
|
|
48
|
+
* const shop = searchParams.get("shop");
|
|
49
|
+
* const customerId = searchParams.get("logged_in_customer_id")
|
|
50
|
+
*
|
|
51
|
+
* return json({my: "data", shop, customerId});
|
|
52
|
+
* };
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
appProxy: AuthenticateAppProxy;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type AuthenticatePublic<Future extends FutureFlagOptions> =
|
|
59
|
+
FeatureEnabled<Future, 'v3_authenticatePublic'> extends true
|
|
60
|
+
? AuthenticatePublicObject
|
|
61
|
+
: AuthenticatePublicLegacy;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Methods for authenticating Requests from Shopify's public surfaces
|
|
65
|
+
*
|
|
66
|
+
* To maintain backwards compatability this is a function and an object.
|
|
67
|
+
*
|
|
68
|
+
* Do not use `authenticate.public()`. Use `authenticate.public.checkout()` instead.
|
|
69
|
+
* `authenticate.public()` will be removed in v2.
|
|
70
|
+
*
|
|
71
|
+
* Methods are:
|
|
72
|
+
*
|
|
73
|
+
* - `authenticate.public.checkout()` for authenticating requests from checkout extensions
|
|
74
|
+
* - `authenticate.public.appProxy()` for authenticating requests from app proxies
|
|
75
|
+
*/
|
|
76
|
+
export type AuthenticatePublicLegacy = AuthenticateCheckout &
|
|
77
|
+
AuthenticatePublicObject;
|