From 64e9ed6676e65df790a36f52fb4a1ca9dbd980b6 Mon Sep 17 00:00:00 2001 From: Locrian24 Date: Tue, 1 Oct 2024 11:45:05 -0700 Subject: [PATCH 1/2] logout on 401 error --- .../component-boilerplate/src/hooks/graphql/useQuery.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/component-boilerplate/src/hooks/graphql/useQuery.ts b/packages/component-boilerplate/src/hooks/graphql/useQuery.ts index c4a8ae638..88ec23555 100644 --- a/packages/component-boilerplate/src/hooks/graphql/useQuery.ts +++ b/packages/component-boilerplate/src/hooks/graphql/useQuery.ts @@ -7,6 +7,7 @@ import { QueryData, useBaseQuery, } from "./useBaseQuery"; +import { setUserIdentity } from "@saasquatch/component-environment"; // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze function deepFreeze(object) { @@ -55,6 +56,11 @@ export function useQuery( useRefreshListener({ skip, update, variables }); + if (state.errors) { + const e = state.errors?.[0]?.extensions?.apiError; + e?.statusCode === 401 && setUserIdentity(undefined); + } + return deepFreeze({ ...state, // can override props when refetching for new pagination, offset, etc From f5f9e9106fb616f9c49621bdc8dc9cc1ec3212d6 Mon Sep 17 00:00:00 2001 From: Locrian24 Date: Tue, 1 Oct 2024 16:39:13 -0700 Subject: [PATCH 2/2] Remove userIdentity if tenantAlias' don't match --- .../src/hooks/graphql/useQuery.ts | 6 ------ .../src/contexts/UserIdentityContext.ts | 10 +++++++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/component-boilerplate/src/hooks/graphql/useQuery.ts b/packages/component-boilerplate/src/hooks/graphql/useQuery.ts index 88ec23555..c4a8ae638 100644 --- a/packages/component-boilerplate/src/hooks/graphql/useQuery.ts +++ b/packages/component-boilerplate/src/hooks/graphql/useQuery.ts @@ -7,7 +7,6 @@ import { QueryData, useBaseQuery, } from "./useBaseQuery"; -import { setUserIdentity } from "@saasquatch/component-environment"; // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze function deepFreeze(object) { @@ -56,11 +55,6 @@ export function useQuery( useRefreshListener({ skip, update, variables }); - if (state.errors) { - const e = state.errors?.[0]?.extensions?.apiError; - e?.statusCode === 401 && setUserIdentity(undefined); - } - return deepFreeze({ ...state, // can override props when refetching for new pagination, offset, etc diff --git a/packages/component-environment/src/contexts/UserIdentityContext.ts b/packages/component-environment/src/contexts/UserIdentityContext.ts index e4cd79083..d5bb991fa 100644 --- a/packages/component-environment/src/contexts/UserIdentityContext.ts +++ b/packages/component-environment/src/contexts/UserIdentityContext.ts @@ -1,7 +1,7 @@ import decode from "jwt-decode"; import { ContextProvider } from "dom-context"; import { equal } from "@wry/equality"; -import { getEnvironmentSDK } from "../environment"; +import { getEnvironmentSDK, getTenantAlias } from "../environment"; import { USER_CONTEXT_NAME, UserIdentity, @@ -62,13 +62,16 @@ export function userIdentityFromJwt(jwt?: string): UserIdentity | undefined { let userId: string | undefined = undefined; let accountId: string | undefined = undefined; + let tenantAlias: string | undefined = undefined; if (isDecodedWidgetAPIJWT(decoded)) { // Pull the accountId and userId from the subject and Base64-decode them + // This also applies to JWTs generated for microsite sessions // NOTE: This is to support classic theme engine widget token generation const matches = decoded.sub.match(/(.*):(.*)@(.*):users/); if (matches?.[1]) accountId = atob(matches[1]); if (matches?.[2]) userId = atob(matches[2]); + if (matches?.[3]) tenantAlias = matches[3]; } else if (isDecodedSquatchJWT(decoded)) { accountId = decoded.user.accountId; userId = decoded.user.id; @@ -79,6 +82,11 @@ export function userIdentityFromJwt(jwt?: string): UserIdentity | undefined { return undefined; } + if (tenantAlias && getTenantAlias() && tenantAlias !== getTenantAlias()) { + debug("tenantAlias in JWT doesn't match environment"); + return undefined; + } + // Check if the JWT has expired if (exp && Date.now() >= exp * 1000) { debug("JWT has expired");