@shopify/shopify-app-remix
Version:
Shopify Remix - to simplify the building of Shopify Apps with Remix
155 lines (151 loc) • 7.76 kB
JavaScript
;
var ensureCorsHeaders = require('../helpers/ensure-cors-headers.js');
var validateSessionToken = require('../helpers/validate-session-token.js');
var getSessionTokenHeader = require('../helpers/get-session-token-header.js');
var rejectBotRequest = require('../helpers/reject-bot-request.js');
var respondToOptionsRequest = require('../helpers/respond-to-options-request.js');
require('@remix-run/server-runtime');
require('../../types.js');
var getShopFromRequest = require('../helpers/get-shop-from-request.js');
var cancel = require('./billing/cancel.js');
var require$1 = require('./billing/require.js');
var request = require('./billing/request.js');
var check = require('./billing/check.js');
var createUsageRecord = require('./billing/create-usage-record.js');
var updateUsageSubscriptionCappedAmount = require('./billing/update-usage-subscription-capped-amount.js');
var createAdminApiContext = require('./helpers/create-admin-api-context.js');
var ensureAppIsEmbeddedIfRequired = require('./helpers/ensure-app-is-embedded-if-required.js');
var ensureSessionTokenSearchParamIfRequired = require('./helpers/ensure-session-token-search-param-if-required.js');
require('@shopify/shopify-api');
var redirect = require('./helpers/redirect.js');
var renderAppBridge = require('./helpers/render-app-bridge.js');
var validateShopAndHostParams = require('./helpers/validate-shop-and-host-params.js');
var factory = require('./scope/factory.js');
function authStrategyFactory({ strategy, ...params }) {
const { api, logger, config } = params;
async function respondToBouncePageRequest(request) {
const url = new URL(request.url);
if (url.pathname === config.auth.patchSessionTokenPath) {
logger.debug('Rendering bounce page', {
shop: getShopFromRequest.getShopFromRequest(request),
});
throw renderAppBridge.renderAppBridge({ config}, request);
}
}
async function respondToExitIframeRequest(request) {
const url = new URL(request.url);
if (url.pathname === config.auth.exitIframePath) {
const destination = url.searchParams.get('exitIframe');
logger.debug('Rendering exit iframe page', {
shop: getShopFromRequest.getShopFromRequest(request),
destination,
});
throw renderAppBridge.renderAppBridge({ config}, request, { url: destination });
}
}
function createContext(request$1, session, authStrategy, sessionToken) {
let context = {
admin: createAdminApiContext.createAdminApiContext(session, params, authStrategy.handleClientError(request$1)),
billing: {
require: require$1.requireBillingFactory(params, request$1, session),
check: check.checkBillingFactory(params, request$1, session),
request: request.requestBillingFactory(params, request$1, session),
cancel: cancel.cancelBillingFactory(params, request$1, session),
createUsageRecord: createUsageRecord.createUsageRecordFactory(params, request$1, session),
updateUsageCappedAmount: updateUsageSubscriptionCappedAmount.updateUsageCappedAmountFactory(params, request$1, session),
},
session,
cors: ensureCorsHeaders.ensureCORSHeadersFactory(params, request$1),
};
context = addEmbeddedFeatures(context, request$1, session, sessionToken);
context = addScopesFeatures(context);
return context;
}
function addEmbeddedFeatures(context, request, session, sessionToken) {
if (config.isEmbeddedApp) {
return {
...context,
sessionToken,
redirect: redirect.redirectFactory(params, request, session.shop),
};
}
return context;
}
function addScopesFeatures(context) {
return {
...context,
scopes: factory.scopesApiFactory(params, context.session, context.admin),
};
}
return async function authenticateAdmin(request) {
try {
rejectBotRequest.respondToBotRequest(params, request);
respondToOptionsRequest.respondToOptionsRequest(params, request);
await respondToBouncePageRequest(request);
await respondToExitIframeRequest(request);
await strategy.respondToOAuthRequests(request);
// If this is a valid request, but it doesn't have a session token header, this is a document request. We need to
// ensure we're embedded if needed and we have the information needed to load the session.
if (!getSessionTokenHeader.getSessionTokenHeader(request)) {
validateShopAndHostParams.validateShopAndHostParams(params, request);
await ensureAppIsEmbeddedIfRequired.ensureAppIsEmbeddedIfRequired(params, request);
await ensureSessionTokenSearchParamIfRequired.ensureSessionTokenSearchParamIfRequired(params, request);
}
logger.info('Authenticating admin request', {
shop: getShopFromRequest.getShopFromRequest(request),
});
const { payload, shop, sessionId, sessionToken } = await getSessionTokenContext(params, request);
logger.debug('Loading session from storage', { shop, sessionId });
const existingSession = sessionId
? await config.sessionStorage.loadSession(sessionId)
: undefined;
const session = await strategy.authenticate(request, {
session: existingSession,
sessionToken,
shop,
});
return createContext(request, session, strategy, payload);
}
catch (errorOrResponse) {
if (errorOrResponse instanceof Response) {
logger.debug('Authenticate returned a response', {
shop: getShopFromRequest.getShopFromRequest(request),
});
ensureCorsHeaders.ensureCORSHeadersFactory(params, request)(errorOrResponse);
}
throw errorOrResponse;
}
};
}
async function getSessionTokenContext(params, request) {
const { api, config, logger } = params;
const headerSessionToken = getSessionTokenHeader.getSessionTokenHeader(request);
const searchParamSessionToken = getSessionTokenHeader.getSessionTokenFromUrlParam(request);
const sessionToken = (headerSessionToken || searchParamSessionToken);
logger.debug('Attempting to authenticate session token', {
shop: getShopFromRequest.getShopFromRequest(request),
sessionToken: JSON.stringify({
header: headerSessionToken,
search: searchParamSessionToken,
}),
});
if (config.isEmbeddedApp) {
const payload = await validateSessionToken.validateSessionToken(params, request, sessionToken);
const dest = new URL(payload.dest);
const shop = dest.hostname;
logger.debug('Session token is valid - authenticated', { shop, payload });
const sessionId = config.useOnlineTokens
? api.session.getJwtSessionId(shop, payload.sub)
: api.session.getOfflineId(shop);
return { shop, payload, sessionId, sessionToken };
}
const url = new URL(request.url);
const shop = url.searchParams.get('shop');
const sessionId = await api.session.getCurrentId({
isOnline: config.useOnlineTokens,
rawRequest: request,
});
return { shop, sessionId, payload: undefined, sessionToken };
}
exports.authStrategyFactory = authStrategyFactory;
//# sourceMappingURL=authenticate.js.map