From 65e4fe50c93a3a942645951b1c0ec1b3788bad49 Mon Sep 17 00:00:00 2001 From: bluebeel Date: Mon, 7 Dec 2020 10:12:34 +0100 Subject: [PATCH] remove logs and update tsconfig --- src/auth/create-oauth-callback.ts | 52 ++++++++++++++++++++++------ src/auth/create-oauth-start.ts | 4 +-- src/auth/redirection-page.ts | 9 +++-- src/index.ts | 2 ++ src/requireAuthentication.ts | 52 ++++++++++++++++++++++++++++ src/verify-request/utilities.ts | 8 ++--- src/verify-request/verify-request.ts | 29 +++++++++------- tsconfig.json | 17 ++++++--- 8 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 src/requireAuthentication.ts diff --git a/src/auth/create-oauth-callback.ts b/src/auth/create-oauth-callback.ts index 3c2af78..9f06e71 100644 --- a/src/auth/create-oauth-callback.ts +++ b/src/auth/create-oauth-callback.ts @@ -1,14 +1,19 @@ -import querystring from 'querystring'; +import querystring from "querystring"; -import type { NextApiRequest, NextApiResponse } from 'next'; +import type { NextApiRequest, NextApiResponse } from "next"; -import {AuthConfig} from '../types'; +import { AuthConfig } from "../types"; import ShopifyError, { ErrorResponse } from "./errors"; -import validateHmac from './validate-hmac'; +import validateHmac from "./validate-hmac"; +//import { setCookie } from '../helpers/cookies'; +import cookie from "cookie"; export default function createOAuthCallback(config: AuthConfig) { - return async function oAuthCallback(req: NextApiRequest,res: NextApiResponse) { + return async function oAuthCallback( + req: NextApiRequest, + res: NextApiResponse + ) { const query = req.query as Record; const { code, hmac, shop, state: nonce } = query; const { apiKey, secret, afterAuth } = config; @@ -52,13 +57,13 @@ export default function createOAuthCallback(config: AuthConfig) { const accessTokenResponse = await fetch( `https://${shop}/admin/oauth/access_token`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': Buffer.byteLength(accessTokenQuery).toString(), + "Content-Type": "application/x-www-form-urlencoded", + "Content-Length": Buffer.byteLength(accessTokenQuery).toString(), }, body: accessTokenQuery, - }, + } ); if (!accessTokenResponse.ok) { @@ -77,9 +82,36 @@ export default function createOAuthCallback(config: AuthConfig) { associated_user: associatedUser, } = accessTokenData; + res.setHeader("Set-Cookie", [ + cookie.serialize("shopOrigin", String(shop), { + secure: true, + httpOnly: false, + sameSite: "none", + path: "/", + }), + cookie.serialize("shopifyToken", String(accessToken), { + secure: true, + httpOnly: false, + sameSite: "none", + path: "/", + }), + cookie.serialize("shopifyAssociatedUser", JSON.stringify(associatedUser), { + secure: true, + httpOnly: false, + sameSite: "none", + path: "/", + }), + ]); if (afterAuth) { - await afterAuth({ shopOrigin: shop, shopifyToken: accessToken, shopifyScope: associatedUserScope, shopifyAssociatedUser: associatedUser, req, res }) + await afterAuth({ + shopOrigin: shop, + shopifyToken: accessToken, + shopifyScope: associatedUserScope, + shopifyAssociatedUser: associatedUser, + req, + res, + }); } }; } diff --git a/src/auth/create-oauth-start.ts b/src/auth/create-oauth-start.ts index c4a3ba2..a83a532 100644 --- a/src/auth/create-oauth-start.ts +++ b/src/auth/create-oauth-start.ts @@ -5,7 +5,7 @@ import {OAuthStartOptions} from '../types'; import ShopifyError, { ErrorResponse } from "./errors"; import oAuthQueryString from './oauth-query-string'; import { DEFAULT_ACCESS_MODE, DEFAULT_MYSHOPIFY_DOMAIN, TOP_LEVEL_OAUTH_COOKIE_NAME } from "./index"; -import {setCookie} from "../helpers/cookies"; +import {destroyCookie} from "../helpers/cookies"; export default function createOAuthStart( options: OAuthStartOptions, @@ -37,7 +37,7 @@ export default function createOAuthStart( return; } - setCookie({res,name: TOP_LEVEL_OAUTH_COOKIE_NAME, value: ''}); + destroyCookie({ res, name: TOP_LEVEL_OAUTH_COOKIE_NAME }); const formattedQueryString = oAuthQueryString(req, res, options, callbackPath); diff --git a/src/auth/redirection-page.ts b/src/auth/redirection-page.ts index 0c0bdc5..54f1854 100644 --- a/src/auth/redirection-page.ts +++ b/src/auth/redirection-page.ts @@ -7,12 +7,16 @@ type RedirectionParams = { export default function redirectionScript({ origin, redirectTo, - apiKey, + apiKey }: RedirectionParams) { return ` `; diff --git a/src/index.ts b/src/index.ts index 8b35ad0..7331747 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,3 +7,5 @@ export * from "./auth"; export * from "./types"; export { default as verifyRequest } from "./verify-request"; + +export { default as authenticateShopifyPage } from "./requireAuthentication"; diff --git a/src/requireAuthentication.ts b/src/requireAuthentication.ts new file mode 100644 index 0000000..5bb56db --- /dev/null +++ b/src/requireAuthentication.ts @@ -0,0 +1,52 @@ +import { + GetServerSidePropsContext, +} from "next"; +import { parseCookies } from "nookies"; +import verifyRequest from "./verify-request/verify-request"; + +// Overwrite ServerResponse to allow `shopOrigin` +interface GetServerSideShopifyPropsContext extends GetServerSidePropsContext { + shopOrigin?: string; +} + + +export type GetServerSideProps< + P extends { [key: string]: any } = { [key: string]: any } +> = (context: GetServerSideShopifyPropsContext) => Promise<{ props: P }>; + +const authenticateShopifyPage = async ( + getServerSidePropsInner: GetServerSideProps = async () => ({ props: {} }) +) => { + const getServerSideProps: GetServerSideProps = async (ctx) => { + const pathname = new URL(ctx.resolvedUrl).pathname; + + const authRoute = "/api/shopify/auth"; + const fallbackRoute = "/login"; + const verifyTokenUrl = `${process.env.HOST}/api/shopify/verify-token`; + const cookies = parseCookies(ctx); + const shopOrigin = ctx.query.shop ?? cookies.shopOrigin; + + if (pathname !== fallbackRoute) { + await verifyRequest({ + query: ctx.query, + cookies, + res: ctx.res, + options: { authRoute, fallbackRoute, verifyTokenUrl }, + }); + } + + ctx.shopOrigin = shopOrigin as string; + + const result = await getServerSidePropsInner(ctx); + + return { + props: { + shopOrigin, + ...result.props, + }, + }; + }; + return getServerSideProps; +}; + +export default authenticateShopifyPage; diff --git a/src/verify-request/utilities.ts b/src/verify-request/utilities.ts index c8766b6..3c07199 100644 --- a/src/verify-request/utilities.ts +++ b/src/verify-request/utilities.ts @@ -1,6 +1,6 @@ import { Routes } from "./types"; import { ServerResponse } from "http"; -import { setCookie } from "../helpers/cookies"; +import { destroyCookie } from "../helpers/cookies"; export function redirectToAuth({ shop, @@ -19,7 +19,7 @@ export function redirectToAuth({ } export function clearSession({ res }: { res?: ServerResponse }) { - setCookie({ res, name: "shopSettingsId", value: "" }); - setCookie({ res, name: "shopOrigin", value: "" }); - setCookie({ res, name: "shopifyToken", value: "" }); + destroyCookie({ res, name: "shopSettingsId" }); + destroyCookie({ res, name: "shopOrigin" }); + destroyCookie({ res, name: "shopifyToken" }); } diff --git a/src/verify-request/verify-request.ts b/src/verify-request/verify-request.ts index 1b44deb..e3fc9b8 100644 --- a/src/verify-request/verify-request.ts +++ b/src/verify-request/verify-request.ts @@ -1,16 +1,16 @@ import { ServerResponse } from "http"; -import {loginAgainIfDifferentShop} from './login-again-if-different-shop'; -import {verifyToken} from './verify-token'; -import {Options, Routes} from './types'; +import { loginAgainIfDifferentShop } from "./login-again-if-different-shop"; +import { verifyToken } from "./verify-token"; +import { Options, Routes } from "./types"; export default async function verifyRequest({ - query, - cookies, - res, - options, - }: { - query: Record; + query, + cookies, + res, + options, +}: { + query: Record; cookies: Record; res?: ServerResponse; options: Options; @@ -21,8 +21,6 @@ export default async function verifyRequest({ }; const shopFromQuery = Array.isArray(query.shop) ? query.shop[0] : query.shop; - console.log("lib", cookies) - console.log("shop", shopFromQuery) if (shopFromQuery && cookies.shopOrigin) { if (shopFromQuery !== cookies.shopOrigin) { // go through login process if different shops @@ -33,6 +31,11 @@ export default async function verifyRequest({ const shopifyToken = cookies.shopifyToken; const shopOrigin = shopFromQuery ?? cookies.shopOrigin; - await verifyToken({ shopOrigin, shopifyToken, res, routes, verifyTokenUrl: options.verifyTokenUrl }); - + await verifyToken({ + shopOrigin, + shopifyToken, + res, + routes, + verifyTokenUrl: options.verifyTokenUrl, + }); } diff --git a/tsconfig.json b/tsconfig.json index ebf1099..fb651d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,27 @@ { "compilerOptions": { "target": "es5", - "module": "commonjs", "moduleResolution": "node", "noUnusedLocals": true, + "importHelpers": true, + "lib": [ + "dom", + "dom.iterable", + "es2015", + "es2016", + "es2017", + "es2018", + "esnext.asynciterable" + ], "rootDir": "src", "outDir": "dist", - "sourceMap": true, + "sourceMap": false, "strict": true, - "lib": ["dom"], "esModuleInterop": true, "declaration": true, "declarationMap": true, - "skipLibCheck": true + "skipLibCheck": true, + "downlevelIteration": true, }, "exclude": ["node_modules", "dist"] }