From e922a553593de293fbb503318867ec5bd3a28a77 Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Thu, 3 Aug 2023 09:20:40 -0400 Subject: [PATCH] Allow not checking session token aud field --- .../markdown_link_checker_config.json | 10 +++++++- .../__tests__/decode-session-token.test.ts | 25 +++++++++++++++++++ lib/session/decode-session-token.ts | 11 ++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/markdown_link_checker_config.json b/.github/workflows/markdown_link_checker_config.json index 0d2a104f3..cbb780483 100644 --- a/.github/workflows/markdown_link_checker_config.json +++ b/.github/workflows/markdown_link_checker_config.json @@ -1,4 +1,12 @@ { "retryOn429": true, - "fallbackRetryDelay": "1s" + "fallbackRetryDelay": "1s", + "httpHeaders": [ + { + "urls": ["https://help.shopify.com"], + "headers": { + "Cookie": "new_help=1" + } + } + ] } diff --git a/lib/session/__tests__/decode-session-token.test.ts b/lib/session/__tests__/decode-session-token.test.ts index 13d54a30e..2539ad309 100644 --- a/lib/session/__tests__/decode-session-token.test.ts +++ b/lib/session/__tests__/decode-session-token.test.ts @@ -65,4 +65,29 @@ describe('JWT session token', () => { ShopifyErrors.InvalidJwtError, ); }); + + test("doesn't fail on a mismatching API key when not checking the token's audience", async () => { + shopify.config.apiKey = 'something_else'; + + // The token is signed with a key that is not the current value + const token = await signJWT(shopify.config.apiSecretKey, payload); + + const actualPayload = await shopify.session.decodeSessionToken(token, { + checkAudience: false, + }); + expect(actualPayload).toStrictEqual(payload); + }); + + test("doesn't fail on a missing aud field when not checking the token's audience", async () => { + const payloadWithoutAud = {...payload}; + delete (payloadWithoutAud as any).aud; + + // The token is signed with a key that is not the current value + const token = await signJWT(shopify.config.apiSecretKey, payload); + + const actualPayload = await shopify.session.decodeSessionToken(token, { + checkAudience: false, + }); + expect(actualPayload).toStrictEqual(payload); + }); }); diff --git a/lib/session/decode-session-token.ts b/lib/session/decode-session-token.ts index cdd5e4031..ff314b133 100644 --- a/lib/session/decode-session-token.ts +++ b/lib/session/decode-session-token.ts @@ -8,8 +8,15 @@ import {JwtPayload} from './types'; const JWT_PERMITTED_CLOCK_TOLERANCE = 10; +export interface DecodeSessionTokenOptions { + checkAudience?: boolean; +} + export function decodeSessionToken(config: ConfigInterface) { - return async (token: string): Promise => { + return async ( + token: string, + {checkAudience = true}: DecodeSessionTokenOptions = {}, + ): Promise => { let payload: JwtPayload; try { payload = ( @@ -26,7 +33,7 @@ export function decodeSessionToken(config: ConfigInterface) { // The exp and nbf fields are validated by the JWT library - if (payload.aud !== config.apiKey) { + if (checkAudience && payload.aud !== config.apiKey) { throw new ShopifyErrors.InvalidJwtError( 'Session token had invalid API key', );