Skip to content

Commit

Permalink
Get shop from token, if available, as last resort
Browse files Browse the repository at this point in the history
If no shop param is provided and no session is found (e.g., app just
uninstalled), then try to get the shop from the token if it's present.
If it's there, use it to redirect to auth, which should lead the user
back to the app install screen.

Fixes #94
  • Loading branch information
mkevinosullivan committed Feb 22, 2023
1 parent 51dc150 commit b176882
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ describe('validateAuthenticatedSession', () => {
).toBe(`/api/auth?shop=my-shop.myshopify.io`);
});

it('no session, no shop param, with auth header, returns 403 with correct headers', async () => {
jest
.spyOn(shopify.api.session, 'getCurrentId')
.mockResolvedValueOnce(undefined);

const response = await request(app)
.get('/test/shop')
.set({Authorization: `Bearer ${validJWT}`})
.expect(403);

expect(
response.headers['x-shopify-api-request-failure-reauthorize'],
).toBe('1');
expect(
response.headers['x-shopify-api-request-failure-reauthorize-url'],
).toBe(`/api/auth?shop=my-shop.myshopify.io`);
});

it('no session, without auth header redirects to auth', async () => {
const response = await request(app)
.get('/test/shop?shop=my-shop.myshopify.io')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function validateAuthenticatedSession({
}
}

const shop = req.query.shop || session?.shop;
let shop = req.query.shop || session?.shop;

if (session && shop && session.shop !== shop) {
config.logger.debug(
Expand Down Expand Up @@ -82,6 +82,17 @@ export function validateAuthenticatedSession({
}
}

const bearerPresent = req.headers.authorization?.match(/Bearer (.*)/);
if (bearerPresent) {
if (!shop) {
shop = await setShopFromSessionOrToken(
api,
session,
bearerPresent[1],
);
}
}

const redirectUrl = `${config.auth.path}?shop=${shop}`;
config.logger.info(
`Session was not valid. Redirecting to ${redirectUrl}`,
Expand All @@ -91,7 +102,7 @@ export function validateAuthenticatedSession({
return returnTopLevelRedirection({
res,
config,
bearerPresent: Boolean(req.headers.authorization?.match(/Bearer (.*)/)),
bearerPresent: Boolean(bearerPresent),
redirectUrl,
});
};
Expand All @@ -110,3 +121,19 @@ async function handleSessionError(_req: Request, res: Response, error: Error) {
break;
}
}

async function setShopFromSessionOrToken(
api: Shopify,
session: Session | undefined,
token: string,
): Promise<string | undefined> {
let shop: string | undefined;

if (session) {
shop = session.shop;
} else if (api.config.isEmbeddedApp) {
const payload = await api.session.decodeSessionToken(token);
shop = payload.dest.replace('https://', '');
}
return shop;
}

0 comments on commit b176882

Please sign in to comment.