From f2b9861b4d208849e31da161f7f3029fa8273f52 Mon Sep 17 00:00:00 2001 From: Jonas Daniels Date: Fri, 9 May 2025 00:52:03 +0200 Subject: [PATCH] Separate authToken from secretKey in ThirdwebClient --- .../src/@/constants/thirdweb.server.ts | 3 +- packages/thirdweb/src/client/client.test.ts | 16 +++++++--- packages/thirdweb/src/client/client.ts | 20 +++++++++--- packages/thirdweb/src/utils/fetch.ts | 31 ++++++------------- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/apps/dashboard/src/@/constants/thirdweb.server.ts b/apps/dashboard/src/@/constants/thirdweb.server.ts index 28cc1f3ac97..d9072fa7ccf 100644 --- a/apps/dashboard/src/@/constants/thirdweb.server.ts +++ b/apps/dashboard/src/@/constants/thirdweb.server.ts @@ -79,7 +79,8 @@ export function getThirdwebClient( return createThirdwebClient({ teamId: options?.teamId, - secretKey: options?.jwt ? options.jwt : DASHBOARD_THIRDWEB_SECRET_KEY, + secretKey: DASHBOARD_THIRDWEB_SECRET_KEY, + authToken: options?.jwt ?? undefined, clientId: DASHBOARD_THIRDWEB_CLIENT_ID, config: { storage: { diff --git a/packages/thirdweb/src/client/client.test.ts b/packages/thirdweb/src/client/client.test.ts index fd83d4a1503..f7ca054061b 100644 --- a/packages/thirdweb/src/client/client.test.ts +++ b/packages/thirdweb/src/client/client.test.ts @@ -29,15 +29,23 @@ describe("client", () => { it("should accept a jwt being passed", () => { const client = createThirdwebClient({ clientId: "foo", - secretKey: "bar.baz.qux", + authToken: "bar.baz.qux", }); expect(client.clientId).toBe("foo"); - expect(client.secretKey).toBe("bar.baz.qux"); + expect(client.authToken).toBe("bar.baz.qux"); + expect(client.secretKey).toBeUndefined(); }); - it("should throw if clientId is missing with JWT input", () => { + + it("should throw an error if authToken is passed as secretKey", () => { expect(() => createThirdwebClient({ secretKey: "bar.baz.qux" }), - ).toThrowError(/clientId must be provided when using a JWT secretKey/); + ).toThrowError(/have to pass authToken directly/); + }); + + it("should throw if clientId is missing with JWT input", () => { + expect(() => + createThirdwebClient({ authToken: "bar.baz.qux", secretKey: "foo" }), + ).toThrowError(/have to pass clientId when passing authToken/); }); }); }); diff --git a/packages/thirdweb/src/client/client.ts b/packages/thirdweb/src/client/client.ts index 4c10e25f30f..cdaa76092dd 100644 --- a/packages/thirdweb/src/client/client.ts +++ b/packages/thirdweb/src/client/client.ts @@ -62,10 +62,12 @@ export type CreateThirdwebClientOptions = Prettify< | { clientId: string; secretKey?: string; + authToken?: string; } | { clientId?: string; secretKey: string; + authToken?: string; } ) & ClientOptions @@ -74,6 +76,11 @@ export type CreateThirdwebClientOptions = Prettify< export type ThirdwebClient = { readonly clientId: string; readonly secretKey: string | undefined; + /** + * The auth token for thirdweb dashboard usage. + * @hidden + */ + readonly authToken: string | undefined; } & Readonly; /** @@ -109,16 +116,18 @@ export type ThirdwebClient = { export function createThirdwebClient( options: CreateThirdwebClientOptions, ): ThirdwebClient { - const { clientId, secretKey, ...rest } = options; + const { clientId, secretKey, authToken, ...rest } = options; let realClientId: string | undefined = clientId; + if (authToken && !clientId) { + // always HAVE to also pass clientId when passing auth token + throw new Error("have to pass clientId when passing authToken"); + } + if (secretKey) { if (isJWT(secretKey)) { - // when passing a JWT as secret key we HAVE to also have a clientId - if (!clientId) { - throw new Error("clientId must be provided when using a JWT secretKey"); - } + throw new Error("have to pass authToken directly"); } else { // always PREFER the clientId if provided, only compute it from the secretKey if we don't have a clientId passed explicitly realClientId = clientId ?? computeClientIdFromSecretKey(secretKey); @@ -132,6 +141,7 @@ export function createThirdwebClient( return { ...rest, + authToken, clientId: realClientId, secretKey, } as const; diff --git a/packages/thirdweb/src/utils/fetch.ts b/packages/thirdweb/src/utils/fetch.ts index 60c55126d6d..be86e11bfe2 100644 --- a/packages/thirdweb/src/utils/fetch.ts +++ b/packages/thirdweb/src/utils/fetch.ts @@ -8,7 +8,6 @@ import { detectPlatform, } from "./detect-platform.js"; import { getServiceKey } from "./domains.js"; -import { isJWT } from "./jwt/is-jwt.js"; import { IS_DEV } from "./process.js"; const DEFAULT_REQUEST_TIMEOUT = 60000; @@ -45,39 +44,29 @@ export function getClientFetch(client: ThirdwebClient, ecosystem?: Ecosystem) { if (!headers) { headers = new Headers(); } - // auth token if secret key === jwt - const authToken = - useAuthToken && client.secretKey && isJWT(client.secretKey) - ? client.secretKey - : undefined; - // secret key if secret key !== jwt - const secretKey = - client.secretKey && !isJWT(client.secretKey) - ? client.secretKey - : undefined; - const clientId = client.clientId; - - // if we have an auth token set, use that (thirdweb dashboard sets this for the user) + + // if we have an auth token set & useAuthToken is true, use the auth token (thirdweb dashboard sets this for the user) // pay urls should never send the auth token, because we always want the "developer" to be the one making the request, not the "end user" if ( - authToken && + useAuthToken && + client.authToken && !isPayUrl(urlString) && !isInAppWalletUrl(urlString) && !isBundlerUrl(urlString) ) { - headers.set("authorization", `Bearer ${authToken}`); + headers.set("authorization", `Bearer ${client.authToken}`); // if we have a specific teamId set, add it to the request headers if (client.teamId) { headers.set("x-team-id", client.teamId); } } - - if (secretKey) { - headers.set("x-secret-key", secretKey); + // never set BOTH auth header and secret key header at the same time, auth header takes precedence + else if (client.secretKey) { + headers.set("x-secret-key", client.secretKey); } - if (clientId) { - headers.set("x-client-id", clientId); + if (client.clientId) { + headers.set("x-client-id", client.clientId); } if (ecosystem) {