From 8655147fc1a5762fdeb8d3adc6e9cd8500895c52 Mon Sep 17 00:00:00 2001 From: Phillip Ho Date: Sun, 8 Jun 2025 18:25:40 +0800 Subject: [PATCH] chore: optional serviceApiKey --- .changeset/good-swans-bet.md | 5 +++++ packages/service-utils/src/core/api.ts | 3 ++- .../src/core/get-auth-headers.test.ts | 10 ++++++++++ .../src/core/get-auth-headers.ts | 19 ++++++++++++------- 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 .changeset/good-swans-bet.md diff --git a/.changeset/good-swans-bet.md b/.changeset/good-swans-bet.md new file mode 100644 index 00000000000..0ae7598391d --- /dev/null +++ b/.changeset/good-swans-bet.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/service-utils": patch +--- + +fix: make service api key optional to allow services to pass through auth diff --git a/packages/service-utils/src/core/api.ts b/packages/service-utils/src/core/api.ts index bb9f141e208..0358afea5f5 100644 --- a/packages/service-utils/src/core/api.ts +++ b/packages/service-utils/src/core/api.ts @@ -20,7 +20,8 @@ export type CoreServiceConfig = { // if EXPLICITLY set to null, service will not be checked for authorization // this is meant for services that are not possible to be turned off by users, such as "social" and "analytics" serviceScope: ServiceName | null; - serviceApiKey: string; + // Optional. Some services pass through user-provided authentication (e.g. analytics) and should not have any authed access on their own. + serviceApiKey?: string; serviceAction?: string; useWalletAuth?: boolean; /** diff --git a/packages/service-utils/src/core/get-auth-headers.test.ts b/packages/service-utils/src/core/get-auth-headers.test.ts index df6042f06eb..301c7ee6b9b 100644 --- a/packages/service-utils/src/core/get-auth-headers.test.ts +++ b/packages/service-utils/src/core/get-auth-headers.test.ts @@ -111,4 +111,14 @@ describe("getAuthHeaders", () => { Authorization: "Bearer test-jwt", }); }); + + it("should return empty headers if no auth method and no serviceApiKey is provided", () => { + const headers = getAuthHeaders(defaultAuthData); + expect(headers).toEqual({}); + }); + + it("should return empty headers if serviceApiKey is undefined and no other auth method is provided", () => { + const headers = getAuthHeaders(defaultAuthData, undefined); + expect(headers).toEqual({}); + }); }); diff --git a/packages/service-utils/src/core/get-auth-headers.ts b/packages/service-utils/src/core/get-auth-headers.ts index 4f0c5e37adc..6eaf5e84526 100644 --- a/packages/service-utils/src/core/get-auth-headers.ts +++ b/packages/service-utils/src/core/get-auth-headers.ts @@ -9,8 +9,8 @@ import type { AuthorizationInput } from "./authorize/index.js"; */ export function getAuthHeaders( authData: AuthorizationInput, - serviceApiKey: string, -): Record { + serviceApiKey?: string, +): HeadersInit { const { teamId, clientId, jwt, secretKey, incomingServiceApiKey } = authData; switch (true) { @@ -18,26 +18,31 @@ export function getAuthHeaders( case !!secretKey: return { "x-secret-key": secretKey, - } as Record; + }; // 2. if we have a JWT AND either a teamId or clientId, we'll use the JWT for auth case !!(jwt && (teamId || clientId)): return { Authorization: `Bearer ${jwt}`, - } as Record; + }; // 3. if we have an incoming service api key, we'll use it case !!incomingServiceApiKey: { return { "x-service-api-key": incomingServiceApiKey, - } as Record; + }; } - // 4. if nothing else is present, we'll use the service api key - default: { + // 4. if we have a service api key provided by the service, use it + case !!serviceApiKey: { return { "x-service-api-key": serviceApiKey, }; } + + // 5. otherwise leave auth headers empty + default: { + return {}; + } } }