From 54774833e1b586d64309b6c1f8dd40b025539c22 Mon Sep 17 00:00:00 2001 From: ascender1729 Date: Wed, 8 Oct 2025 00:25:31 +0530 Subject: [PATCH] fix: correct API key prefix config key from api.apiKeyPrefix to api.keyPrefix Fixes #23683 This fixes a critical authentication bug where API key validation was failing with 401 Unauthorized errors. Root Cause: The configuration file (apps/api/v2/src/config/app.ts) defines the API key prefix as api.keyPrefix, but multiple authentication files were incorrectly referencing api.apiKeyPrefix. When config.get("api.apiKeyPrefix") was called, it returned undefined, causing the code to fall back to the default "cal_" prefix. However, if a custom API_KEY_PREFIX environment variable was configured, this inconsistency between the check and strip operations would cause: 1. API key detection to use default "cal_" prefix 2. API key stripping to use the actual configured prefix 3. Mismatched hash computation 4. Database lookup failure 5. 401 Unauthorized error Changes: - Updated api-auth.strategy.ts (2 occurrences) - Updated bookings.controller.ts for 2024-04-15 API - Updated input.service.ts for 2024-08-13 API - Updated permissions.guard.ts - Updated permissions.guard.spec.ts test file All now correctly use api.keyPrefix to match the configuration schema. Impact: Resolves 401 errors for Elevenlabs integration and all other API users attempting to use the /v2/bookings endpoint with API keys. --- .../ee/bookings/2024-04-15/controllers/bookings.controller.ts | 2 +- .../v2/src/ee/bookings/2024-08-13/services/input.service.ts | 2 +- .../modules/auth/guards/permissions/permissions.guard.spec.ts | 2 +- .../src/modules/auth/guards/permissions/permissions.guard.ts | 2 +- .../src/modules/auth/strategies/api-auth/api-auth.strategy.ts | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts b/apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts index 9b2c06301a9f7e..a47f47ff93bca3 100644 --- a/apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts +++ b/apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts @@ -384,7 +384,7 @@ export class BookingsController_2024_04_15 { try { const bearerToken = req.get("Authorization")?.replace("Bearer ", ""); if (bearerToken) { - if (isApiKey(bearerToken, this.config.get("api.apiKeyPrefix") ?? "cal_")) { + if (isApiKey(bearerToken, this.config.get("api.keyPrefix") ?? "cal_")) { const strippedApiKey = stripApiKey(bearerToken, this.config.get("api.keyPrefix")); const apiKeyHash = sha256Hash(strippedApiKey); const keyData = await this.apiKeyRepository.getApiKeyFromHash(apiKeyHash); diff --git a/apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts b/apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts index de185c48d62e63..4cf9305740fb14 100644 --- a/apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts +++ b/apps/api/v2/src/ee/bookings/2024-08-13/services/input.service.ts @@ -680,7 +680,7 @@ export class InputBookingsService_2024_08_13 { try { const bearerToken = req.get("Authorization")?.replace("Bearer ", ""); if (bearerToken) { - if (isApiKey(bearerToken, this.config.get("api.apiKeyPrefix") ?? "cal_")) { + if (isApiKey(bearerToken, this.config.get("api.keyPrefix") ?? "cal_")) { const strippedApiKey = stripApiKey(bearerToken, this.config.get("api.keyPrefix")); const apiKeyHash = sha256Hash(strippedApiKey); const keyData = await this.apiKeyRepository.getApiKeyFromHash(apiKeyHash); diff --git a/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.spec.ts b/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.spec.ts index e2baca38459cba..6846fa928111b2 100644 --- a/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.spec.ts +++ b/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.spec.ts @@ -24,7 +24,7 @@ describe("PermissionsGuard", () => { createMock({ get: jest.fn().mockImplementation((key: string) => { switch (key) { - case "api.apiKeyPrefix": + case "api.keyPrefix": return "cal_"; default: return null; diff --git a/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.ts b/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.ts index ac14f182d178e0..2711390392973a 100644 --- a/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.ts +++ b/apps/api/v2/src/modules/auth/guards/permissions/permissions.guard.ts @@ -36,7 +36,7 @@ export class PermissionsGuard implements CanActivate { const nextAuthSecret = this.config.get("next.authSecret", { infer: true }); const nextAuthToken = await getToken({ req: request, secret: nextAuthSecret }); const oAuthClientId = request.params?.clientId || request.get(X_CAL_CLIENT_ID); - const apiKey = bearerToken && isApiKey(bearerToken, this.config.get("api.apiKeyPrefix") ?? "cal_"); + const apiKey = bearerToken && isApiKey(bearerToken, this.config.get("api.keyPrefix") ?? "cal_"); const isThirdPartyBearerToken = bearerToken && this.getDecodedThirdPartyAccessToken(bearerToken); // only check permissions for accessTokens attached to platform oAuth Client or platform oAuth credentials, not for next token or api key or third party oauth client diff --git a/apps/api/v2/src/modules/auth/strategies/api-auth/api-auth.strategy.ts b/apps/api/v2/src/modules/auth/strategies/api-auth/api-auth.strategy.ts index 9f24bea005ee5b..cbcc89bf67a889 100644 --- a/apps/api/v2/src/modules/auth/strategies/api-auth/api-auth.strategy.ts +++ b/apps/api/v2/src/modules/auth/strategies/api-auth/api-auth.strategy.ts @@ -88,7 +88,7 @@ export class ApiAuthStrategy extends PassportStrategy(BaseStrategy, "api-auth") if (apiKeyAllowed || accessTokenAllowed) { try { const requestOrigin = request.get("Origin"); - request.authMethod = isApiKey(bearerToken, this.config.get("api.apiKeyPrefix") ?? "cal_") + request.authMethod = isApiKey(bearerToken, this.config.get("api.keyPrefix") ?? "cal_") ? AuthMethods["API_KEY"] : AuthMethods["ACCESS_TOKEN"]; return await this.authenticateBearerToken(bearerToken, request, requestOrigin); @@ -216,7 +216,7 @@ export class ApiAuthStrategy extends PassportStrategy(BaseStrategy, "api-auth") requestOrigin: string | undefined ) { try { - const user = isApiKey(authString, this.config.get("api.apiKeyPrefix") ?? "cal_") + const user = isApiKey(authString, this.config.get("api.keyPrefix") ?? "cal_") ? await this.apiKeyStrategy(authString, request) : await this.accessTokenStrategy(authString, request, requestOrigin);