The current AzureOpenAI auto-configuration code assume that the users will provide a static api key if no key is set, then an exception is throw see https://github.com/spring-projects/spring-ai/blob/ca1949c8250187d94d735665b2044a844234aa51/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/azure/openai/AzureOpenAiAutoConfiguration.java#L66
Azure supports a keyless authentication mode that uses Azure Active Directory and system identity. Some users of Azure will disable key based accessed for the Azure Open AI service and those users can't use spring-ai with azure open ai.
Todo: - Enhance the the AzureOpenAiAutoConfiguration to support keyless authentication. - Document how users can configure keyless authentication
Reference https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/authentication
Resources: - https://github.com/Azure-Samples/azure-openai-keyless-java
Comment From: KKulma
I second this—at the very least, please provide documentation on how to update relevant scripts to enable authentication via Service Principal. We're wrestling with it at the moment, and autoconfiguration is stubbornly hard to override!
Comment From: frankliu20
Vote for this.
Keyless authentication is more secure and recommended apporach when using Azure Open AI. There is an builder which requires developer to build the TokenCredential
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(TokenCredential.class)
public OpenAIClientBuilder openAIClientWithTokenCredential(AzureOpenAiConnectionProperties connectionProperties,
TokenCredential tokenCredential) {
Assert.notNull(tokenCredential, "TokenCredential must not be null");
Assert.hasText(connectionProperties.getEndpoint(), "Endpoint must not be empty");
return new OpenAIClientBuilder().endpoint(connectionProperties.getEndpoint())
.credential(tokenCredential)
.clientOptions(new ClientOptions().setApplicationId(APPLICATION_ID));
}
While, this is not convinent enough, and it requires the devlopers to lean and build a TokenCredential
by themself. I suppose, we should just add a TokenCredential
bean here with the DefaultAzureCredentialBuilder
in case no one feed that.
@Bean
@ConditionalOnMissingBean
public TokenCredential AzureTokenCredential() {
TokenCredential defaultCredential = new DefaultAzureCredentialBuilder().build();
return defaultCredential;
}