Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
Allow not checking session token aud field
Browse files Browse the repository at this point in the history
  • Loading branch information
paulomarg committed Aug 3, 2023
1 parent 52976cf commit 6148967
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-hounds-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/shopify-api': patch
---

Allow not checking a session token payload's `aud` field to support tokens generated outside of the Shopify Admin.
10 changes: 9 additions & 1 deletion .github/workflows/markdown_link_checker_config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
{
"retryOn429": true,
"fallbackRetryDelay": "1s"
"fallbackRetryDelay": "1s",
"httpHeaders": [
{
"urls": ["https://help.shopify.com"],
"headers": {
"Cookie": "new_help=1"
}
}
]
}
13 changes: 13 additions & 0 deletions docs/reference/session/decodeSessionToken.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ app.get('/fetch-some-data', async (req, res) => {

The token to parse.

### options

`Object`

An object that allows the following fields:

#### checkAudience

`boolean` | Defaults to `true`

Whether the method should check the `aud` field in the decoded payload.
This should always be set to `true` if the token is coming from the Shopify Admin.

## Return

`Promise<JwtPayload>`
Expand Down
25 changes: 25 additions & 0 deletions lib/session/__tests__/decode-session-token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
11 changes: 9 additions & 2 deletions lib/session/decode-session-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<JwtPayload> => {
return async (
token: string,
{checkAudience = true}: DecodeSessionTokenOptions = {},
): Promise<JwtPayload> => {
let payload: JwtPayload;
try {
payload = (
Expand All @@ -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',
);
Expand Down

0 comments on commit 6148967

Please sign in to comment.