diff --git a/src/create-client.ts b/src/create-client.ts index 8e6c58f..f9ead7c 100644 --- a/src/create-client.ts +++ b/src/create-client.ts @@ -12,7 +12,7 @@ import { removeSessionData, storageKeys, } from "./utils"; -import { getRefreshToken } from "./utils/session-data"; +import { getRefreshToken, getClaims } from "./utils/session-data"; import { RedirectParams } from "./interfaces/create-client-options.interface"; import Lock from "./vendor/browser-tabs-lock"; import { RefreshError } from "./utils/authenticate-with-refresh-token"; @@ -28,6 +28,8 @@ type State = "INITIAL" | "AUTHENTICATING" | "AUTHENTICATED" | "ERROR"; const DEFAULT_HOSTNAME = "api.workos.com"; +const ORGANIZATION_ID_SESSION_STORAGE_KEY = "workos_organization_id"; + export async function createClient( clientId: string, options: CreateClientOptions = {}, @@ -115,12 +117,17 @@ export async function createClient( return user ? (user as User) : null; } + function _getAccessToken() { + return memoryStorage.getItem(storageKeys.accessToken) as string | undefined; + } + async function getAccessToken() { // TODO: should this respect onBeforeAutoRefresh ? if (_needsRefresh()) { await refreshSession(); } - return memoryStorage.getItem(storageKeys.accessToken) as string | undefined; + + return _getAccessToken(); } let _refreshTimer: ReturnType | undefined; @@ -209,7 +216,9 @@ export async function createClient( const REFRESH_LOCK = "WORKOS_REFRESH_SESSION"; - async function refreshSession() { + async function refreshSession({ + organizationId, + }: { organizationId?: string } = {}) { if ( _authkitClientState !== "AUTHENTICATED" && _authkitClientState !== "INITIAL" @@ -220,11 +229,29 @@ export async function createClient( const lock = new Lock(); try { _authkitClientState = "AUTHENTICATING"; + if (await lock.acquireLock(REFRESH_LOCK)) { + if (organizationId) { + sessionStorage.setItem( + ORGANIZATION_ID_SESSION_STORAGE_KEY, + organizationId, + ); + } else { + const accessToken = _getAccessToken(); + if (accessToken) { + organizationId = getClaims(accessToken)?.org_id; + } else { + organizationId = + sessionStorage.getItem(ORGANIZATION_ID_SESSION_STORAGE_KEY) ?? + undefined; + } + } + const authenticationResponse = await authenticateWithRefreshToken({ baseUrl: _baseUrl, clientId: _clientId, refreshToken: getRefreshToken({ devMode }), + organizationId, useCookie: _useCookie, }); diff --git a/src/utils/authenticate-with-refresh-token.ts b/src/utils/authenticate-with-refresh-token.ts index d6f36be..16f25b1 100644 --- a/src/utils/authenticate-with-refresh-token.ts +++ b/src/utils/authenticate-with-refresh-token.ts @@ -5,15 +5,19 @@ interface AuthenticateWithRefreshTokenOptions { baseUrl: string; clientId: string; refreshToken: string | undefined; + organizationId?: string; useCookie: boolean; } export class RefreshError extends Error {} -export async function authenticateWithRefreshToken( - options: AuthenticateWithRefreshTokenOptions, -) { - const { baseUrl, clientId, refreshToken, useCookie } = options; +export async function authenticateWithRefreshToken({ + baseUrl, + clientId, + refreshToken, + organizationId, + useCookie, +}: AuthenticateWithRefreshTokenOptions) { const response = await fetch(`${baseUrl}/user_management/authenticate`, { method: "POST", ...(useCookie && { credentials: "include" }), @@ -25,6 +29,7 @@ export async function authenticateWithRefreshToken( client_id: clientId, grant_type: "refresh_token", ...(!useCookie && { refresh_token: refreshToken }), + organization_id: organizationId, }), });