🔐 feat: Implement Entra ID authentication for Azure OpenAI integration

- Added support for Entra ID authentication in OpenAIClient and related services.
- Updated header management to conditionally use Entra ID access tokens or API keys based on environment configuration.
- Introduced utility functions for Entra ID token retrieval and credential management.
- Enhanced tests to verify Entra ID authentication flow and its integration with Azure configurations.
This commit is contained in:
victorbjorkgren 2025-09-12 17:29:43 +02:00 committed by victorbjor
parent a1471c2f37
commit 9288e84454
9 changed files with 212 additions and 18 deletions

View file

@ -6,6 +6,8 @@ const {
getOpenAIConfig,
getAzureCredentials,
createHandleLLMNewToken,
shouldUseEntraId,
getEntraIdAccessToken,
} = require('@librechat/api');
const { getUserKeyValues, checkUserKeyExpiry } = require('~/server/services/UserService');
const OpenAIClient = require('~/app/clients/OpenAIClient');
@ -106,11 +108,25 @@ const initializeClient = async ({
clientOptions.defaultQuery = azureOptions.azureOpenAIApiVersion
? { 'api-version': azureOptions.azureOpenAIApiVersion }
: undefined;
clientOptions.headers['api-key'] = apiKey;
if (shouldUseEntraId()) {
clientOptions.headers = {
...clientOptions.headers,
Authorization: `Bearer ${await getEntraIdAccessToken()}`,
};
} else {
clientOptions.headers['api-key'] = apiKey;
}
}
} else if (isAzureOpenAI) {
clientOptions.azure = userProvidesKey ? JSON.parse(userValues.apiKey) : getAzureCredentials();
apiKey = clientOptions.azure.azureOpenAIApiKey;
if (shouldUseEntraId()) {
clientOptions.headers = {
...clientOptions.headers,
Authorization: `Bearer ${await getEntraIdAccessToken()}`,
};
apiKey = 'entra-id-placeholder';
}
}
/** @type {undefined | TBaseEndpoint} */

View file

@ -428,4 +428,29 @@ describe('initializeClient', () => {
expect(result.openAIApiKey).toBe('test');
expect(result.client.options.reverseProxyUrl).toBe('https://user-provided-url.com');
});
test('should use Entra ID authentication when AZURE_OPENAI_USE_ENTRA_ID is enabled', async () => {
process.env.AZURE_OPENAI_USE_ENTRA_ID = 'true';
process.env.AZURE_API_KEY = 'test-azure-api-key';
process.env.AZURE_OPENAI_API_INSTANCE_NAME = 'test-instance';
process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME = 'test-deployment';
process.env.AZURE_OPENAI_API_VERSION = '2024-12-01-preview';
const req = {
body: {
key: null,
endpoint: EModelEndpoint.azureOpenAI,
model: 'gpt-4-vision-preview',
},
user: { id: '123' },
app: { locals: {} },
config: mockAppConfig,
};
const res = {};
const endpointOption = {};
const result = await initializeClient({ req, res, endpointOption });
expect(result.openAIApiKey).toBeTruthy();
});
});