{"version":3,"file":"validate-authenticated-session.mjs","sources":["../../../../src/middlewares/validate-authenticated-session.ts"],"sourcesContent":["import {Session, Shopify, InvalidJwtError} from '@shopify/shopify-api';\nimport {Request, Response, NextFunction} from 'express';\n\nimport {redirectToAuth} from '../redirect-to-auth';\nimport {ApiAndConfigParams} from '../types';\nimport {redirectOutOfApp} from '../redirect-out-of-app';\n\nimport {ValidateAuthenticatedSessionMiddleware} from './types';\nimport {hasValidAccessToken} from './has-valid-access-token';\n\ntype validateAuthenticatedSessionParams = ApiAndConfigParams;\n\nexport function validateAuthenticatedSession({\n  api,\n  config,\n}: validateAuthenticatedSessionParams): ValidateAuthenticatedSessionMiddleware {\n  return function validateAuthenticatedSession() {\n    return async (req: Request, res: Response, next: NextFunction) => {\n      config.logger.debug('Running validateAuthenticatedSession');\n\n      let sessionId: string | undefined;\n      try {\n        sessionId = await api.session.getCurrentId({\n          isOnline: config.useOnlineTokens,\n          rawRequest: req,\n          rawResponse: res,\n        });\n      } catch (error) {\n        config.logger.error(\n          `Error when loading session from storage: ${error}`,\n        );\n\n        handleSessionError(req, res, error);\n        return undefined;\n      }\n\n      let session: Session | undefined;\n      if (sessionId) {\n        try {\n          session = await config.sessionStorage.loadSession(sessionId);\n        } catch (error) {\n          config.logger.error(\n            `Error when loading session from storage: ${error}`,\n          );\n\n          res.status(500);\n          res.send(error.message);\n          return undefined;\n        }\n      }\n\n      let shop =\n        api.utils.sanitizeShop(req.query.shop as string) || session?.shop;\n\n      if (session && shop && session.shop !== shop) {\n        config.logger.debug(\n          'Found a session for a different shop in the request',\n          {currentShop: session.shop, requestShop: shop},\n        );\n\n        return redirectToAuth({req, res, api, config});\n      }\n\n      if (session) {\n        config.logger.debug('Request session found and loaded', {\n          shop: session.shop,\n        });\n\n        if (session.isActive(api.config.scopes)) {\n          config.logger.debug('Request session exists and is active', {\n            shop: session.shop,\n          });\n\n          if (await hasValidAccessToken(api, session)) {\n            config.logger.debug('Request session has a valid access token', {\n              shop: session.shop,\n            });\n\n            res.locals.shopify = {\n              ...res.locals.shopify,\n              session,\n            };\n            return next();\n          }\n        }\n      }\n\n      const bearerPresent = req.headers.authorization?.match(/Bearer (.*)/);\n      if (bearerPresent) {\n        if (!shop) {\n          shop = await setShopFromSessionOrToken(\n            api,\n            session,\n            bearerPresent[1],\n          );\n        }\n      }\n\n      const redirectUri = `${config.auth.path}?shop=${shop}`;\n      config.logger.info(\n        `Session was not valid. Redirecting to ${redirectUri}`,\n        {shop},\n      );\n\n      return redirectOutOfApp({api, config})({\n        req,\n        res,\n        redirectUri,\n        shop: shop!,\n      });\n    };\n  };\n}\n\nfunction handleSessionError(_req: Request, res: Response, error: Error) {\n  switch (true) {\n    case error instanceof InvalidJwtError:\n      res.status(401);\n      res.send(error.message);\n      break;\n    default:\n      res.status(500);\n      res.send(error.message);\n      break;\n  }\n}\n\nasync function setShopFromSessionOrToken(\n  api: Shopify,\n  session: Session | undefined,\n  token: string,\n): Promise<string | undefined> {\n  let shop: string | undefined;\n\n  if (session) {\n    shop = session.shop;\n  } else if (api.config.isEmbeddedApp) {\n    const payload = await api.session.decodeSessionToken(token);\n    shop = payload.dest.replace('https://', '');\n  }\n  return shop;\n}\n"],"names":[],"mappings":"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"}