Koa Shopify Authentication Middleware
simple-koa-shopify-auth is a Koa middleware library designed to simplify Shopify app authentication, serving as a successor to the now-deprecated `@shopify/koa-shopify-auth`. It specifically supports `@shopify/shopify-api` version 5.x.x, integrating features like token exchange for online sessions and removing cookie-based session management to reduce redirects. The package is currently at version 3.0.0, with patch updates for performance and bug fixes, but the project is officially considered deprecated by its maintainer due to ongoing improvements in Shopify's native authentication flows that will render such a library unnecessary. It differentiates itself by its explicit support for `@shopify/shopify-api` v5 and its streamlined session handling, but it is not affiliated with Shopify directly. There are no plans to support `@shopify/shopify-api` v6 or newer versions, making it suitable only for applications locked into the v5 API.
Common errors
-
TypeError: Cannot destructure property 'shopify' of 'ctx.state' as it is undefined.
cause The `simple-koa-shopify-auth` middleware (or `@shopify/shopify-api`'s `validateAuthenticatedSession`) was not correctly applied or executed before accessing `ctx.state.shopify`.fixEnsure `app.use(shopify.validateAuthenticatedSession());` and the `createShopifyAuth` middleware are correctly registered and executed in the Koa application's middleware stack. The `shopify` object from `@shopify/shopify-api` must also be correctly initialized with `isOnline: true`. -
Error: Missing Shopify API environment variables. Please check your .env file.
cause Required environment variables (SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SCOPES, HOST) are not set or loaded.fixCreate a `.env` file in your project root with the necessary variables and ensure `dotenv.config();` is called at the start of your application. -
ERR_REQUIRE_ESM: require() of ES Module [path] from [path] not supported. Instead, change the require of [path] to a dynamic import() or top-level await.
cause `simple-koa-shopify-auth` is an ES Module (ESM) but is being imported using CommonJS `require()` syntax.fixChange your import statements from `const { createShopifyAuth } = require('simple-koa-shopify-auth');` to `import { createShopifyAuth } from 'simple-koa-shopify-auth';`. Ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json`). -
Error: Shopify API v5 is required but current version is not 5.x.x.
cause Your project's `@shopify/shopify-api` dependency is not version 5.x.x, which is a strict requirement for `simple-koa-shopify-auth`.fixInstall the correct version: `npm uninstall @shopify/shopify-api && npm install @shopify/shopify-api@^5.3.0`.
Warnings
- breaking The `verifyRequest` middleware now returns a `401 Unauthorized` status code for invalid sessions, instead of the `403 Forbidden` returned by the original `@shopify/koa-shopify-auth` library. Client-side handling must be updated accordingly.
- deprecated This package is officially considered DEPRECATED by its maintainer. Shopify's own authentication mechanisms (like token exchange) are evolving, which will make this library unnecessary in the future.
- breaking This library only supports `@shopify/shopify-api` v5. There are no plans to support v6+ currently, which means upgrading your `@shopify/shopify-api` dependency beyond v5 will break `simple-koa-shopify-auth`.
- gotcha Versions 2.1.0 through 2.1.3 of `simple-koa-shopify-auth` are known to be broken and should not be used.
- breaking As of v3.0.0, the `verifyRequest` middleware attempts to use the Shopify token exchange API to get a new online session if the current one is invalid. This changes the authentication flow for online sessions.
Install
-
npm install simple-koa-shopify-auth -
yarn add simple-koa-shopify-auth -
pnpm add simple-koa-shopify-auth
Imports
- createShopifyAuth
import createShopifyAuth from 'simple-koa-shopify-auth';
import { createShopifyAuth } from 'simple-koa-shopify-auth'; - verifyRequest
const { verifyRequest } = require('simple-koa-shopify-auth');import { verifyRequest } from 'simple-koa-shopify-auth'; - AuthOptions
import type { AuthOptions } from 'simple-koa-shopify-auth';
Quickstart
import Koa from 'koa';
import Router from '@koa/router';
import dotenv from 'dotenv';
import { createShopifyAuth, verifyRequest } from 'simple-koa-shopify-auth';
import '@shopify/shopify-api/adapters/node'; // Must be imported before initializing Shopify API
import { shopifyApi, LATEST_API_VERSION } from '@shopify/shopify-api';
dotenv.config();
const app = new Koa();
const router = new Router();
const { SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SCOPES, HOST } = process.env;
if (!SHOPIFY_API_KEY || !SHOPIFY_API_SECRET || !SCOPES || !HOST) {
throw new Error('Missing Shopify API environment variables. Please check your .env file.');
}
const shopify = shopifyApi({
apiKey: SHOPIFY_API_KEY,
apiSecretKey: SHOPIFY_API_SECRET,
scopes: SCOPES.split(','),
hostName: HOST.replace(/https?:\/\//, ''),
apiVersion: LATEST_API_VERSION,
is</div>Online: true // crucial for online sessions with simple-koa-shopify-auth
});
// Register authentication routes
router.get('/auth', createShopifyAuth({
async afterAuth(ctx) {
const { shop, accessToken } = ctx.state.shopify;
console.log(`Authenticated shop: ${shop} with access token: ${accessToken}`);
// Redirect to your app's main page or dashboard
ctx.redirect(`https://${shop}/admin/apps/${shopify.config.apiKey}`);
}
}));
// Middleware to verify requests for authenticated routes
const verifyPageRequest = verifyRequest();
const verifyApiRequest = verifyRequest({ returnHeader: true });
// Example protected route for app pages
router.get('/', verifyPageRequest, async (ctx) => {
ctx.body = 'Welcome to your Shopify App!';
});
// Example protected route for API endpoints
router.get('/api/data', verifyApiRequest, async (ctx) => {
const { shop, accessToken } = ctx.state.shopify;
ctx.body = { message: `Data for ${shop}`, token: accessToken };
});
app.use(shopify.validateAuthenticatedSession()); // Necessary for session management with shopify-api v5
app.use(router.routes()).use(router.allowedMethods());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Shopify API Key: ${SHOPIFY_API_KEY}`);
});