{"version":3,"file":"authenticate.mjs","sources":["../../../../../../../src/server/authenticate/public/appProxy/authenticate.ts"],"sourcesContent":["import {adminClientFactory, storefrontClientFactory} from '../../../clients';\nimport {ensureValidOfflineSession} from '../../../helpers';\nimport {BasicParams} from '../../../types';\n\nimport {\n  AppProxyContext,\n  AppProxyContextWithSession,\n  AuthenticateAppProxy,\n  LiquidResponseFunction,\n} from './types';\n\nexport function authenticateAppProxyFactory(\n  params: BasicParams,\n): AuthenticateAppProxy {\n  const {logger} = params;\n\n  return async function authenticate(\n    request: Request,\n  ): Promise<AppProxyContext | AppProxyContextWithSession> {\n    const url = new URL(request.url);\n    const shop = url.searchParams.get('shop')!;\n    logger.info('Authenticating app proxy request', {shop});\n\n    if (!(await validateAppProxyHmac(params, url))) {\n      logger.info('App proxy request has invalid signature', {shop});\n      throw new Response(undefined, {\n        status: 400,\n        statusText: 'Bad Request',\n      });\n    }\n\n    const session = await ensureValidOfflineSession(params, shop);\n\n    if (!session) {\n      logger.debug('Could not find offline session, returning empty context', {\n        shop,\n        ...Object.fromEntries(url.searchParams.entries()),\n      });\n\n      const context: AppProxyContext = {\n        liquid,\n        session: undefined,\n        admin: undefined,\n        storefront: undefined,\n      };\n\n      return context;\n    }\n\n    const context: AppProxyContextWithSession = {\n      liquid,\n      session,\n      admin: adminClientFactory({params, session}),\n      storefront: storefrontClientFactory({params, session}),\n    };\n\n    return context;\n  };\n}\n\nconst liquid: LiquidResponseFunction = (body, initAndOptions) => {\n  const processedBody = processLiquidBody(body);\n\n  if (typeof initAndOptions !== 'object') {\n    return new Response(processedBody, {\n      status: initAndOptions || 200,\n      headers: {\n        'Content-Type': 'application/liquid',\n      },\n    });\n  }\n\n  const {layout, ...responseInit} = initAndOptions || {};\n  const responseBody =\n    layout === false ? `{% layout none %} ${processedBody}` : processedBody;\n\n  const headers = new Headers(responseInit.headers);\n  headers.set('Content-Type', 'application/liquid');\n\n  return new Response(responseBody, {\n    ...responseInit,\n    headers,\n  });\n};\n\nasync function validateAppProxyHmac(\n  params: BasicParams,\n  url: URL,\n): Promise<boolean> {\n  const {api, logger} = params;\n\n  try {\n    let searchParams = new URLSearchParams(url.search);\n    if (!searchParams.get('index')) {\n      searchParams.delete('index');\n    }\n\n    let isValid = await api.utils.validateHmac(\n      Object.fromEntries(searchParams.entries()),\n      {signator: 'appProxy'},\n    );\n\n    if (!isValid) {\n      const cleanPath = url.pathname\n        .replace(/^\\//, '')\n        .replace(/\\/$/, '')\n        .replaceAll('/', '.');\n      const data = `routes%2F${cleanPath}`;\n\n      searchParams = new URLSearchParams(\n        `?_data=${data}&${searchParams.toString().replace(/^\\?/, '')}`,\n      );\n\n      isValid = await api.utils.validateHmac(\n        Object.fromEntries(searchParams.entries()),\n        {signator: 'appProxy'},\n      );\n\n      if (!isValid) {\n        const searchParams = new URLSearchParams(\n          `?_data=${data}._index&${url.search.replace(/^\\?/, '')}`,\n        );\n\n        isValid = await api.utils.validateHmac(\n          Object.fromEntries(searchParams.entries()),\n          {signator: 'appProxy'},\n        );\n      }\n    }\n\n    return isValid;\n  } catch (error) {\n    const shop = url.searchParams.get('shop')!;\n    logger.info(error.message, {shop});\n    throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n  }\n}\n\nfunction processLiquidBody(body: string) {\n  return (\n    body\n      // Add trailing slashes to relative form action URLs\n      .replaceAll(\n        /<(form[^>]+)action=\"(\\/[^\"?]+)(\\?[^\"]+)?\">/g,\n        '<$1action=\"$2/$3\">',\n      )\n      // Add trailing slashes to relative link href URLs\n      .replaceAll(/<(a[^>]+)href=\"(\\/[^\"?]+)(\\?[^\"]+)?\">/g, '<$1href=\"$2/$3\">')\n  );\n}\n"],"names":[],"mappings":"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"}