Skip to content

Conversation

@TejasGhatte
Copy link
Collaborator

@TejasGhatte TejasGhatte commented Dec 19, 2025

Summary

Added Azure Entra ID (Service Principal) authentication support to the Azure provider, allowing for more secure token-based authentication with automatic token management.

Changes

  • Implemented Service Principal authentication for Azure using ClientID, ClientSecret, and TenantID credentials
  • Added token caching with a sync.Map to avoid repeated authentication requests
  • Updated the Azure provider to use a priority-based authentication approach:
    1. Service Principal (if credentials provided)
    2. Context token (if available)
    3. API key (fallback)
  • Added new fields to the AzureKeyConfig schema in both Go and UI
  • Created database migration for the new Azure authentication fields
  • Updated documentation to explain the new authentication options
  • Added UI form fields for the new Azure authentication parameters

Type of change

  • Feature
  • Documentation

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • UI (Next.js)
  • Docs

How to test

  1. Configure Azure Service Principal credentials:
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_ENDPOINT="https://your-azure-endpoint.openai.azure.com"
  1. Use the credentials in your application:
key := schemas.Key{
    Models: []string{"gpt-4o"},
    AzureKeyConfig: &schemas.AzureKeyConfig{
        Endpoint:     os.Getenv("AZURE_ENDPOINT"),
        ClientID:     bifrost.Ptr(os.Getenv("AZURE_CLIENT_ID")),
        ClientSecret: bifrost.Ptr(os.Getenv("AZURE_CLIENT_SECRET")),
        TenantID:     bifrost.Ptr(os.Getenv("AZURE_TENANT_ID")),
        Deployments: map[string]string{
            "gpt-4o": "gpt-4o-deployment",
        },
    },
}
  1. Run tests to verify authentication works:
go test ./providers/azure/...

Breaking changes

  • No

Related issues

Enhances Azure authentication options for enterprise deployments.

Security considerations

  • Service Principal credentials are sensitive and should be stored securely
  • The implementation uses the official Azure SDK for authentication
  • Token caching is implemented to reduce authentication requests
  • Credentials can be provided via environment variables for better security

Checklist

  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 19, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added Azure Entra ID (service principal) authentication (Client ID / Client Secret / Tenant ID) with centralized token handling and fallback to API key.
    • UI: Azure provider form now exposes Client ID, Client Secret, and Tenant ID fields.
  • Documentation

    • Updated Azure provider guide to explain dual authentication paths and env-var usage.
  • Chores

    • Database migration and config/redaction/merge logic updated to store and preserve new Azure credential fields.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds Azure Entra ID (service principal) support by introducing ClientID/ClientSecret/TenantID fields, centralizing Azure auth to prefer service-principal tokens over context tokens and API keys, persisting credentials via DB migration/storage, adding redaction/env-var handling, and exposing UI/documentation for the new fields.

Changes

Cohort / File(s) Summary
Go Dependencies
core/go.mod
Added Azure SDK (.../azcore, .../azidentity), MSAL, JWT and related indirect dependency updates.
Schemas & Types
core/schemas/account.go, ui/lib/types/config.ts, ui/lib/types/schemas.ts, ui/lib/schemas/providerForm.ts
Added optional Azure OAuth fields client_id, client_secret, tenant_id to AzureKeyConfig and updated defaults/schemas.
Azure Provider (auth logic)
core/providers/azure/azure.go, core/providers/azure/files.go, core/internal/testutil/account.go
Introduced DefaultAzureScope, credential cache (sync.Map), getOrCreateAuth, and getAzureAuthHeaders; centralized auth flow prioritizing service principal → context token → API key. setAzureAuth now returns *schemas.BifrostError.
Database Tables & Migrations
framework/configstore/tables/key.go, framework/configstore/tables/virtualkey.go, framework/configstore/migrations.go
Added AzureClientID, AzureClientSecret, AzureTenantID columns and migration; BeforeSave/AfterFind propagate these fields; virtual keys clear them. Renamed BedrockBatchS3ConfigBedrockBatchS3ConfigJSON.
HTTP Layer & Redaction
transports/bifrost-http/handlers/providers.go, transports/bifrost-http/lib/config.go
mergeKeys preserves raw Azure credential values when updates are redacted; redaction/env-var resolution extended to client_id/client_secret/tenant_id.
UI & Docs
ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx, docs/quickstart/go-sdk/provider-configuration.mdx
Added UI inputs and guidance for Azure Entra ID fields; docs updated to describe dual authentication (Service Principal vs direct key).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Handler as Request Handler
    participant Provider as AzureProvider
    participant Store as Config Store / DB
    participant AzureSDK as Azure Identity SDK

    Handler->>Provider: Incoming request referencing a key
    Provider->>Store: Load key (may include client_id/secret/tenant or api key)
    alt Service Principal configured
        Provider->>AzureSDK: getOrCreateAuth(clientID, clientSecret, tenantID)
        AzureSDK-->>Provider: TokenCredential / AccessToken
        Provider->>Handler: Attach "Authorization: Bearer <token>"
    else Context token available
        Provider->>Handler: Attach "Authorization: Bearer <context token>"
    else Fallback to API key
        Provider->>Handler: Attach "api-key" / "x-api-key" header with key value
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas needing extra attention:

  • core/providers/azure/azure.go — credential cache (sync.Map) concurrency, token creation, error wrapping.
  • core/providers/azure/files.go — new error-returning setAzureAuth and propagation across callers.
  • framework/configstore/migrations.go — migration idempotence and rollback correctness for different DB backends.
  • framework/configstore/tables/key.go — BeforeSave/AfterFind correctness and BedrockBatchS3Config rename impact.
  • transports/bifrost-http/lib/config.go & handlers/providers.go — redaction/env-var resolution and mergeKeys raw-value preservation.

Poem

🐰
I hopped through headers, keys, and token song,
Three tiny fields now help the flow along.
Client, secret, tenant snug and bright,
I fetch a token — hop! — and set it right.
A carrot, a cookie, and auth done light. 🥕🔑

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main feature: adding Azure Entra ID Service Principal authentication support to the Azure provider.
Description check ✅ Passed The PR description is comprehensive, covering all required template sections with specific details about changes, testing instructions, security considerations, and affected areas.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 12-16-feat_support_client_id_and_client_secret_in_azure

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

🧪 Test Suite Available

This PR can be tested by a repository admin.

Run tests for PR #1133

Copy link
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@TejasGhatte TejasGhatte changed the title feat: support client id and client secret in azure feat: support azure entra id service principal authentication Dec 19, 2025
@TejasGhatte TejasGhatte marked this pull request as ready for review December 19, 2025 06:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (7)
ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1)

231-243: Consider using password input type for Client Secret field.

For improved security posture, the Client Secret field could use type="password" to mask the input value while typing. This would be consistent with security best practices for credential inputs, though I note other secret fields in this form also use plain text inputs.

🔎 Suggested change
 								<FormControl>
-									<Input placeholder="your-client-secret or env.AZURE_CLIENT_SECRET" {...field} value={field.value ?? ""} />
+									<Input placeholder="your-client-secret or env.AZURE_CLIENT_SECRET" type="password" {...field} value={field.value ?? ""} />
 								</FormControl>
transports/bifrost-http/handlers/providers.go (1)

767-791: LGTM! Redaction logic correctly preserves raw Azure credentials.

The implementation properly handles the new Service Principal fields (ClientID, ClientSecret, TenantID) by preserving the original raw values when the incoming update contains redacted values that match the old redacted values. This follows the same pattern used for APIVersion above.

🔎 Optional: Minor redundant check cleanup

The oldRawKey.AzureKeyConfig != nil check within each inner block (lines 770, 778, 786) is redundant since the outer block at line 754 already verifies this condition. You could simplify by removing these redundant checks for cleaner code:

 				if updateKey.AzureKeyConfig.ClientID != nil &&
-					oldRedactedKey.AzureKeyConfig.ClientID != nil &&
-					oldRawKey.AzureKeyConfig != nil {
+					oldRedactedKey.AzureKeyConfig.ClientID != nil {
 					if lib.IsRedacted(*updateKey.AzureKeyConfig.ClientID) &&

This is purely cosmetic and matches the existing style, so feel free to keep as-is.

ui/lib/schemas/providerForm.ts (1)

76-79: LGTM! Schema correctly defines optional Azure credential fields.

The fields are properly defined as optional strings, consistent with the Go backend's pointer types (*string).

🔎 Optional: Consider validation for Service Principal completeness

For Service Principal authentication, all three fields (ClientID, ClientSecret, TenantID) are typically required together. You could add a refinement to validate that either all three are provided or none:

const AzureKeyConfigSchema = z.object({
  endpoint: z.string().min(1, "Endpoint is required for Azure keys"),
  deployments: z.union([z.record(z.string(), z.string()), z.string()]).optional()
    .refine((value) => !value || isValidDeployments(value), { message: "..." }),
  api_version: z.string().optional(),
  client_id: z.string().optional(),
  client_secret: z.string().optional(),
  tenant_id: z.string().optional(),
}).refine((data) => {
  const hasClientId = !!data.client_id?.trim();
  const hasClientSecret = !!data.client_secret?.trim();
  const hasTenantId = !!data.tenant_id?.trim();
  const allProvided = hasClientId && hasClientSecret && hasTenantId;
  const noneProvided = !hasClientId && !hasClientSecret && !hasTenantId;
  return allProvided || noneProvided;
}, {
  message: "For Service Principal auth, provide all of Client ID, Client Secret, and Tenant ID, or leave all empty",
  path: ["client_id"],
});

This is optional since the backend likely handles this validation, but it would provide better UX feedback.

framework/configstore/migrations.go (1)

1833-1874: LGTM! Migration correctly adds Azure credential columns.

The migration follows established patterns in this file:

  • Uses HasColumn checks before AddColumn for idempotency
  • Proper error wrapping with descriptive messages
  • Clean rollback implementation
🔎 Optional: Defensive rollback checks

For consistency with some other migrations (e.g., migrationAddEnabledColumnToKeyTable at line 1134), you could add HasColumn checks in the rollback to make it more defensive:

 		Rollback: func(tx *gorm.DB) error {
 			tx = tx.WithContext(ctx)
 			migrator := tx.Migrator()
+			if migrator.HasColumn(&tables.TableKey{}, "azure_client_id") {
 			if err := migrator.DropColumn(&tables.TableKey{}, "azure_client_id"); err != nil {
 				return fmt.Errorf("failed to drop azure_client_id column: %w", err)
 			}
+			}
 			// ... similar for other columns

This is optional since the current pattern matches other simpler migrations in this file.

transports/bifrost-http/lib/config.go (1)

3439-3495: Env‑var processing for new Azure fields is correct; small redundancy nit.

processAzureKeyConfigEnvVars correctly:

  • Resolves client_id, client_secret, and tenant_id via processEnvValue.
  • Tracks EnvKeyInfo entries with fully qualified ConfigPath matching redaction paths.

Minor nit: azureConfig.ClientSecret is assigned &processedClientSecret twice (before and after the envVar block). You can drop one of the assignments to avoid confusion; behavior is currently correct.

core/providers/azure/files.go (1)

8-8: setAzureAuth behavior matches new auth priority; consider reusing getAzureAuthHeaders.

Service principal → context token → API key ordering and header mangling (Authorization vs api-key) look correct and consistent with the centralized getAzureAuthHeaders logic.

To reduce drift between code paths, you could implement setAzureAuth by delegating to getAzureAuthHeaders(ctx, key, false) and then applying the returned map to req.Header, instead of duplicating the token acquisition logic.

Also applies to: 15-56

core/providers/azure/azure.go (1)

32-44: Centralized Azure auth and token cache look good; cache key should include clientSecret to respect rotations.

The new pieces:

  • DefaultAzureScope and getOrCreateAuth(tenantID, clientID, clientSecret) using azidentity.NewClientSecretCredential.
  • credentials sync.Map on AzureProvider.
  • getAzureAuthHeaders implementing the auth priority (service principal → context token → API key, with x-api-key for Anthropic).

are all aligned with the intended behavior.

One gotcha: the credentials cache key is tenantID + ":" + clientID, so if the client secret is rotated for a given (tenant, client), getOrCreateAuth will continue to reuse the old TokenCredential and never see the new secret until the process restarts or the map is cleared. To support secret rotation, consider including the secret (or a hash of it) in the cache key, or explicitly clearing the corresponding entry when provider config changes.

Also applies to: 46-69, 71-114

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 628fb20 and d8e54ff.

⛔ Files ignored due to path filters (1)
  • core/go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • core/go.mod (4 hunks)
  • core/internal/testutil/account.go (1 hunks)
  • core/providers/azure/azure.go (19 hunks)
  • core/providers/azure/files.go (1 hunks)
  • core/schemas/account.go (1 hunks)
  • docs/quickstart/go-sdk/provider-configuration.mdx (2 hunks)
  • framework/configstore/migrations.go (2 hunks)
  • framework/configstore/tables/key.go (5 hunks)
  • framework/configstore/tables/virtualkey.go (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (3 hunks)
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1 hunks)
  • ui/lib/schemas/providerForm.ts (1 hunks)
  • ui/lib/types/config.ts (1 hunks)
  • ui/lib/types/schemas.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • ui/lib/schemas/providerForm.ts
  • core/schemas/account.go
  • transports/bifrost-http/handlers/providers.go
  • framework/configstore/tables/virtualkey.go
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx
  • docs/quickstart/go-sdk/provider-configuration.mdx
  • core/providers/azure/files.go
  • transports/bifrost-http/lib/config.go
  • core/providers/azure/azure.go
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
  • core/go.mod
  • core/internal/testutil/account.go
  • framework/configstore/tables/key.go
  • framework/configstore/migrations.go
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/schemas/account.go
  • transports/bifrost-http/handlers/providers.go
  • framework/configstore/tables/virtualkey.go
  • core/providers/azure/files.go
  • transports/bifrost-http/lib/config.go
  • core/providers/azure/azure.go
  • core/internal/testutil/account.go
  • framework/configstore/tables/key.go
  • framework/configstore/migrations.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/handlers/providers.go
  • transports/bifrost-http/lib/config.go
🧬 Code graph analysis (5)
core/providers/azure/azure.go (5)
core/schemas/provider.go (1)
  • NetworkConfig (48-56)
core/schemas/account.go (2)
  • Key (8-19)
  • AzureKeyConfig (23-31)
core/providers/utils/utils.go (1)
  • NewBifrostOperationError (733-744)
core/utils.go (1)
  • Ptr (56-58)
core/providers/azure/types.go (1)
  • AzureAPIVersionDefault (4-4)
ui/lib/types/config.ts (1)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
core/internal/testutil/account.go (2)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/utils.go (1)
  • Ptr (56-58)
framework/configstore/tables/key.go (2)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-31)
framework/configstore/migrations.go (2)
framework/migrator/migrator.go (3)
  • New (131-149)
  • DefaultOptions (100-106)
  • Migration (62-69)
framework/configstore/tables/key.go (2)
  • TableKey (13-61)
  • TableKey (64-64)
🪛 GitHub Actions: PR #1133
framework/configstore/tables/key.go

[error] 90-90: k.AzureKeyConfig.ClientID undefined (type *schemas.AzureKeyConfig has no field or method ClientID)

🔇 Additional comments (14)
core/go.mod (3)

5-23: Dependency additions align well with Azure Entra ID feature.

The changes add the necessary Azure SDK modules (azcore, azidentity) and transitive dependencies (MSAL, JWT, crypto utilities) to support Service Principal authentication. The additions are minimal and focused. Ensure the build verification passed in the CI/CD pipeline and that all new dependencies integrate without conflicts.

Verify that:

  • go mod download and go build succeed with these new dependencies.
  • No conflicting versions between direct and transitive dependencies exist.
  • The codebase is using these new modules as expected (should be confirmed by the broader PR changes).

Also applies to: 25-70


49-49: Consider upgrading golang-jwt/jwt/v5 to the latest stable release.

The golang.org/x/crypto v0.45.0 dependency correctly addresses two security vulnerabilities in the SSH package and SSH Agent package. However, a security advisory exists for the golang-jwt/jwt/v5 line regarding excessive memory allocation during header parsing. Verify that v5.3.0 includes the fix for this advisory or upgrade to the latest available v5.x release.


6-7: The Azure SDK versions specified (azcore v1.20.0 and azidentity v1.13.1) are both stable and recently released (November 2025). azcore v1.20.0 was published on November 6, 2025, and azidentity v1.13.1 was released on November 10, 2025. Both versions are stable as they have reached major version v1. No known security advisories were found for these versions. The timing of their releases (within a few days) suggests compatibility testing has been performed. These versions are appropriate for Azure Entra ID (Service Principal) authentication support.

docs/quickstart/go-sdk/provider-configuration.mdx (1)

349-412: LGTM! Clear documentation for the dual authentication methods.

The documentation correctly explains both authentication paths with appropriate code examples. The note at lines 410-412 clearly indicates the authentication priority logic.

framework/configstore/tables/virtualkey.go (1)

56-58: LGTM! Consistent sensitive data redaction for new Azure credentials.

The new Azure credential fields (AzureClientID, AzureClientSecret, AzureTenantID) are correctly cleared in the AfterFind hook, following the established pattern for other sensitive fields. This prevents credential leakage when querying virtual key provider configurations.

core/schemas/account.go (1)

27-30: LGTM! Clean schema additions for Azure Service Principal credentials.

The new fields follow established patterns: optional pointer types (*string), proper JSON tags with omitempty, and clear documentation comments. The naming is consistent with other credential fields in the codebase.

core/internal/testutil/account.go (1)

222-225: LGTM!

The new Azure Service Principal credentials are correctly wired from environment variables using the established bifrost.Ptr() pattern, consistent with how other optional fields (e.g., SessionToken, Region) are handled elsewhere in this file.

ui/lib/types/config.ts (2)

37-41: Verify default values align with backend expectations.

The defaults initialize scope to an empty array []. If this field is not supported by the backend, sending an empty array could cause validation issues or be silently ignored. The other fields (client_id, client_secret, tenant_id) defaulting to empty strings is consistent with optional credential fields.


27-31: Mismatch: scope field exists in TypeScript but not in Go backend schema.

The TypeScript AzureKeyConfig interface includes an optional scope: string[] field, but the Go backend AzureKeyConfig struct (core/schemas/account.go lines 23-31) does not have a corresponding Scope field. The backend internally uses a hardcoded DefaultAzureScope constant instead. This means the UI will send a scope value that the backend cannot deserialize or use, creating a silent data loss scenario.

Either remove the scope field from the TypeScript interface if it's not needed, or add support for it in the Go backend schema if it's intended for future use.

framework/configstore/migrations.go (1)

113-115: Migration integration looks correct.

The new migration is properly placed at the end of the triggerMigrations function, maintaining the sequential migration order.

transports/bifrost-http/lib/config.go (1)

3294-3305: Azure env‑var diffing for client_id / client_secret / tenant_id looks consistent.

Extending getFieldValue to surface client_id, client_secret, and tenant_id for isEnvVarReferenceChanging keeps Azure env‑tracking aligned with existing Endpoint/APIVersion handling; no issues spotted.

framework/configstore/tables/key.go (1)

45-52: Bedrock JSON field rename and hooks wiring look correct.

Renaming to BedrockBatchS3ConfigJSON and using sonic.Marshal/json.Unmarshal in BeforeSave/AfterFind is consistent with existing BedrockDeploymentsJSON handling. No functional issues spotted.

Also applies to: 151-193, 269-304

core/providers/azure/azure.go (2)

171-183: Usage of getAzureAuthHeaders across completion / list / streaming paths is consistent.

All the updated call sites (completeRequest, listModelsByKey, text/chat/responses streams, SpeechStream) now:

  • Call getAzureAuthHeaders(ctx, key, isAnthropicModel) with the correct isAnthropicModel flag.
  • Propagate *schemas.BifrostError directly on failure.
  • Apply the returned header map to the outgoing request or pass it to shared OpenAI/Anthropic streaming helpers.

This unifies auth behavior across Azure endpoints and correctly handles Authorization vs api-key / x-api-key based on model type.

Also applies to: 256-263, 408-412, 549-552, 596-599, 736-739, 769-772, 915-918


1308-1310: File and batch APIs now return Bifrost errors from setAzureAuth; behavior is coherent.

The various file/batch methods (FileUpload, FileList, FileRetrieve, FileDelete, FileContent, BatchCreate, BatchList, BatchRetrieve, BatchCancel) now:

  • Use setAzureAuth(ctx, req, key) and propagate *schemas.BifrostError on failure.
  • Continue to build URLs and handle responses as before.

This keeps auth handling for these endpoints aligned with the new service principal / context token / API key priority without changing their external behavior.

Also applies to: 1415-1417, 1521-1526, 1617-1622, 1744-1749, 1865-1867, 1986-1988, 2087-2092, 2185-2190

@TejasGhatte TejasGhatte force-pushed the 12-16-feat_support_client_id_and_client_secret_in_azure branch from d8e54ff to 3dd5373 Compare December 19, 2025 06:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1)

214-216: Minor grammar issue in alert text.

The word "both" implies two items, but three fields are listed (Client ID, Client Secret, and Tenant ID).

🔎 Suggested fix
 					<AlertDescription>
-						Leave both Client ID, Client Secret and Tenant ID empty to use Azure Entra ID attached to your environment.
+						Leave Client ID, Client Secret, and Tenant ID empty to use Azure Entra ID attached to your environment.
 					</AlertDescription>
ui/lib/types/schemas.ts (1)

21-24: Scope field in TypeScript schema is not reflected in Go backend or UI form.

The scope field (z.array(z.string()).optional()) exists here but is missing from:

  • Go AzureKeyConfig struct in core/schemas/account.go
  • UI form fields in apiKeysFormFragment.tsx

The Azure provider uses a hardcoded default scope (https://cognitiveservices.azure.com/.default). If this field is reserved for future customization, add a comment. Otherwise, remove it to maintain consistency.

🧹 Nitpick comments (7)
transports/bifrost-http/handlers/providers.go (1)

753-792: Azure SP field merge behavior looks correct; optional small tidy‑up.

The preservation logic for ClientID, ClientSecret, and TenantID when the UI sends back redacted/env values matches the existing pattern for Value and APIVersion, and should correctly keep raw creds on no‑change updates. The extra oldRawKey.AzureKeyConfig != nil checks inside each field block are redundant given the outer guard, but that’s cosmetic and can be left as‑is or simplified later.

docs/quickstart/go-sdk/provider-configuration.mdx (1)

349-413: Azure auth docs align with implementation; consider aligning API version with default (optional).

The Service Principal vs direct key flow and env‑var usage look consistent with the backend changes. If you want to avoid confusion later, you might update the example APIVersion to match the default noted in schemas.AzureKeyConfig’s comment, but this is purely a docs polish.

transports/bifrost-http/lib/config.go (2)

3294-3305: getFieldValue Azure extensions correctly support env‑key cleanup.

Adding client_id, client_secret, and tenant_id here allows isEnvVarReferenceChanging to treat the new Azure fields like the existing endpoint/api_version/Vertex/Bedrock fields, so env‑key entries are cleaned up when these references change. Logic and field names line up with the config paths set in processAzureKeyConfigEnvVars.


3439-3495: Env‑var processing for Azure SP fields is correct; only minor duplication nit.

processAzureKeyConfigEnvVars now processes ClientID, ClientSecret, and TenantID via processEnvValue and tracks them as "azure_config" EnvKeyInfos with precise ConfigPaths, which is what GetProviderConfigRedacted and cleanup helpers expect. The double assignment to azureConfig.ClientSecret is harmless but could be collapsed to a single assignment after the env‑tracking block for clarity.

framework/configstore/migrations.go (1)

1858-1870: Rollback doesn't guard column existence before dropping.

The Migrate function checks HasColumn before adding, but the Rollback unconditionally drops columns. If migration partially failed (e.g., only azure_client_id was added), rolling back will error on non-existent columns. Consider adding guards for consistency with the migrate path.

🔎 Suggested improvement
 		Rollback: func(tx *gorm.DB) error {
 			tx = tx.WithContext(ctx)
 			migrator := tx.Migrator()
-			if err := migrator.DropColumn(&tables.TableKey{}, "azure_client_id"); err != nil {
-				return fmt.Errorf("failed to drop azure_client_id column: %w", err)
+			if migrator.HasColumn(&tables.TableKey{}, "azure_client_id") {
+				if err := migrator.DropColumn(&tables.TableKey{}, "azure_client_id"); err != nil {
+					return fmt.Errorf("failed to drop azure_client_id column: %w", err)
+				}
 			}
-			if err := migrator.DropColumn(&tables.TableKey{}, "azure_client_secret"); err != nil {
-				return fmt.Errorf("failed to drop azure_client_secret column: %w", err)
+			if migrator.HasColumn(&tables.TableKey{}, "azure_client_secret") {
+				if err := migrator.DropColumn(&tables.TableKey{}, "azure_client_secret"); err != nil {
+					return fmt.Errorf("failed to drop azure_client_secret column: %w", err)
+				}
 			}
-			if err := migrator.DropColumn(&tables.TableKey{}, "azure_tenant_id"); err != nil {
-				return fmt.Errorf("failed to drop azure_tenant_id column: %w", err)
+			if migrator.HasColumn(&tables.TableKey{}, "azure_tenant_id") {
+				if err := migrator.DropColumn(&tables.TableKey{}, "azure_tenant_id"); err != nil {
+					return fmt.Errorf("failed to drop azure_tenant_id column: %w", err)
+				}
 			}
 			return nil
 		},
ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1)

231-243: Consider using type="password" for the Client Secret field.

The Client Secret is a sensitive credential. Using type="password" would mask the input, consistent with security best practices and similar to how API keys are typically handled in forms.

🔎 Suggested fix
 					<FormField
 						control={control}
 						name={`key.azure_key_config.client_secret`}
 						render={({ field }) => (
 							<FormItem>
 								<FormLabel>Client Secret (Optional)</FormLabel>
 								<FormControl>
-									<Input placeholder="your-client-secret or env.AZURE_CLIENT_SECRET" {...field} value={field.value ?? ""} />
+									<Input type="password" placeholder="your-client-secret or env.AZURE_CLIENT_SECRET" {...field} value={field.value ?? ""} />
 								</FormControl>
 								<FormMessage />
 							</FormItem>
 						)}
 					/>
core/providers/azure/azure.go (1)

46-69: Credential caching doesn't account for secret rotation.

The cache key is tenantID:clientID, so if a user rotates clientSecret without changing the other values, the stale credential remains cached indefinitely. Consider either:

  1. Including a hash of clientSecret in the cache key
  2. Adding a TTL or cache invalidation mechanism
  3. Documenting that service restart is required after secret rotation
🔎 Option 1: Include secret in cache key
 func (p *AzureProvider) getOrCreateAuth(
 	tenantID, clientID, clientSecret string,
 ) (azcore.TokenCredential, error) {
-	key := tenantID + ":" + clientID
+	key := tenantID + ":" + clientID + ":" + clientSecret

 	// Fast path
 	if val, ok := p.credentials.Load(key); ok {
 		return val.(azcore.TokenCredential), nil
 	}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8e54ff and 3dd5373.

⛔ Files ignored due to path filters (1)
  • core/go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • core/go.mod (4 hunks)
  • core/internal/testutil/account.go (1 hunks)
  • core/providers/azure/azure.go (19 hunks)
  • core/providers/azure/files.go (1 hunks)
  • core/schemas/account.go (1 hunks)
  • docs/quickstart/go-sdk/provider-configuration.mdx (2 hunks)
  • framework/configstore/migrations.go (2 hunks)
  • framework/configstore/tables/key.go (5 hunks)
  • framework/configstore/tables/virtualkey.go (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (3 hunks)
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1 hunks)
  • ui/lib/schemas/providerForm.ts (1 hunks)
  • ui/lib/types/config.ts (1 hunks)
  • ui/lib/types/schemas.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • core/schemas/account.go
  • ui/lib/schemas/providerForm.ts
  • ui/lib/types/config.ts
  • core/go.mod
  • framework/configstore/tables/virtualkey.go
  • core/internal/testutil/account.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/handlers/providers.go
  • framework/configstore/tables/key.go
  • framework/configstore/migrations.go
  • core/providers/azure/azure.go
  • ui/lib/types/schemas.ts
  • docs/quickstart/go-sdk/provider-configuration.mdx
  • core/providers/azure/files.go
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/handlers/providers.go
  • framework/configstore/tables/key.go
  • framework/configstore/migrations.go
  • core/providers/azure/azure.go
  • core/providers/azure/files.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/handlers/providers.go
🧬 Code graph analysis (6)
transports/bifrost-http/lib/config.go (4)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/utils.go (1)
  • Ptr (56-58)
framework/configstore/clientconfig.go (1)
  • EnvKeyInfo (26-32)
transports/bifrost-http/handlers/providers.go (3)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
transports/bifrost-http/lib/config.go (1)
  • IsRedacted (3030-3053)
framework/configstore/tables/key.go (2)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
framework/configstore/migrations.go (2)
framework/migrator/migrator.go (3)
  • New (131-149)
  • DefaultOptions (100-106)
  • Migration (62-69)
framework/configstore/tables/key.go (2)
  • TableKey (13-61)
  • TableKey (64-64)
core/providers/azure/azure.go (5)
core/schemas/provider.go (1)
  • NetworkConfig (48-56)
core/schemas/account.go (2)
  • Key (8-19)
  • AzureKeyConfig (23-31)
core/providers/utils/utils.go (1)
  • NewBifrostOperationError (733-744)
core/schemas/utils.go (2)
  • IsAnthropicModel (1048-1050)
  • Ptr (16-18)
core/utils.go (1)
  • Ptr (56-58)
core/providers/azure/files.go (5)
core/providers/azure/azure.go (2)
  • DefaultAzureScope (33-33)
  • AzureAuthorizationTokenKey (30-30)
core/schemas/account.go (2)
  • Key (8-19)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
core/providers/utils/utils.go (1)
  • NewBifrostOperationError (733-744)
core/schemas/bifrost.go (1)
  • Azure (36-36)
🪛 GitHub Actions: PR #1133
framework/configstore/tables/key.go

[error] 90-90: AzureKeyConfig: 'ClientID' is not a field of *schemas.AzureKeyConfig. (undefined field or method 'ClientID')

🔇 Additional comments (13)
transports/bifrost-http/lib/config.go (1)

2169-2196: Azure credential redaction behavior is solid and consistent.

The redaction for ClientID, ClientSecret, and TenantID mirrors the existing pattern: env‑backed values become env.VAR_NAME, and non‑env secrets are masked with RedactKey. This closes the earlier clear‑text ClientSecret gap and keeps all three fields out of API responses while still preserving editability via redacted markers.

framework/configstore/tables/key.go (4)

29-36: TableKey Azure credential columns are well‑shaped and match schema.

The added AzureClientID, AzureClientSecret, and AzureTenantID fields give a clear, 1:1 mapping to schemas.AzureKeyConfig and use appropriate DB types (text for secrets, varchar for IDs). This is consistent with how Vertex/Bedrock fields are modeled.


45-51: Bedrock JSON column naming/usage is coherent.

The explicit BedrockBatchS3ConfigJSON column alongside BedrockDeploymentsJSON keeps JSON blobs isolated and matches how you marshal/unmarshal these structures later in BeforeSave/AfterFind. No issues here.


83-110: Azure BeforeSave mapping correctly persists new SP fields.

When AzureKeyConfig is present, all three SP fields are copied to their dedicated DB columns and fully cleared when the config is nil, which keeps the row state consistent with the virtual struct. This matches the existing endpoint/api_version/deployments handling.


211-219: Azure AfterFind reconstruction matches the stored schema and avoids leaks.

Rebuilding schemas.AzureKeyConfig from AzureEndpoint, AzureAPIVersion, and the new AzureClient*/AzureTenantID columns is straightforward and symmetrical with BeforeSave. Since redaction happens in GetProviderConfigRedacted, returning raw values here is appropriate for internal use.

framework/configstore/migrations.go (1)

1833-1874: Migration implementation looks good.

The migration follows the established patterns in the codebase: proper migration ID, HasColumn guards on the migrate path, context propagation, and error wrapping.

ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1)

209-256: New Azure Entra ID authentication UI section looks well-structured.

The form fields are properly wired to the schema, follow the existing patterns in the file, and provide clear guidance to users through the Alert component.

ui/lib/types/schemas.ts (1)

21-23: Client ID, Client Secret, and Tenant ID fields are correctly added.

These three fields align with the Go backend schema and the UI form implementation.

core/providers/azure/files.go (1)

15-56: Authentication implementation follows correct priority and handles all cases.

The three-tier authentication priority (Service Principal → Context token → API key) is implemented correctly with proper error handling. The header management (setting Authorization and removing api-key, or vice versa) ensures clean authentication state.

core/providers/azure/azure.go (4)

71-114: Centralized authentication header logic is well-designed.

The getAzureAuthHeaders function cleanly encapsulates the three-tier authentication priority and correctly handles the header differences between Anthropic models (x-api-key) and standard Azure OpenAI models (api-key).


170-182: Auth header application in completeRequest is correct.

Headers are retrieved via the centralized method and properly applied to the request before sending.


549-599: Streaming methods consistently use centralized auth.

Both Anthropic and non-Anthropic code paths correctly call getAzureAuthHeaders with the appropriate isAnthropicModel flag.


1308-1310: File and batch operations correctly handle auth errors.

The setAzureAuth return value is now checked at all call sites, and errors are properly propagated or accumulated in the retry loops.

Also applies to: 1415-1417, 1521-1526, 1617-1622, 1744-1749, 1865-1867, 1986-1988, 2087-2092, 2185-2190

@TejasGhatte TejasGhatte force-pushed the 12-16-feat_support_client_id_and_client_secret_in_azure branch from 3dd5373 to be1b879 Compare December 19, 2025 08:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
transports/bifrost-http/lib/config.go (1)

3294-3305: Env-var handling for new Azure fields is wired correctly (minor cleanup possible)

getFieldValue and processAzureKeyConfigEnvVars now understand client_id, client_secret, and tenant_id, so env-key tracking and cleanup work for these fields just like for endpoint/api_version and other provider configs. The pointer checks and processEnvValue usage are safe.

One small nit: azureConfig.ClientSecret is assigned &processedClientSecret twice in the client_secret block; you can drop the earlier assignment without changing behavior to keep the function slightly cleaner.

Also applies to: 3440-3495

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3dd5373 and be1b879.

⛔ Files ignored due to path filters (1)
  • core/go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • core/go.mod (4 hunks)
  • core/internal/testutil/account.go (1 hunks)
  • core/providers/azure/azure.go (19 hunks)
  • core/providers/azure/files.go (1 hunks)
  • core/schemas/account.go (1 hunks)
  • docs/quickstart/go-sdk/provider-configuration.mdx (2 hunks)
  • framework/configstore/migrations.go (2 hunks)
  • framework/configstore/tables/key.go (5 hunks)
  • framework/configstore/tables/virtualkey.go (1 hunks)
  • transports/bifrost-http/handlers/providers.go (1 hunks)
  • transports/bifrost-http/lib/config.go (3 hunks)
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx (1 hunks)
  • ui/lib/schemas/providerForm.ts (1 hunks)
  • ui/lib/types/config.ts (1 hunks)
  • ui/lib/types/schemas.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • core/internal/testutil/account.go
  • ui/lib/types/config.ts
  • core/go.mod
  • ui/lib/types/schemas.ts
  • framework/configstore/migrations.go
  • framework/configstore/tables/virtualkey.go
  • ui/lib/schemas/providerForm.ts
  • ui/app/workspace/providers/fragments/apiKeysFormFragment.tsx
  • docs/quickstart/go-sdk/provider-configuration.mdx
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • transports/bifrost-http/handlers/providers.go
  • core/providers/azure/files.go
  • core/schemas/account.go
  • transports/bifrost-http/lib/config.go
  • framework/configstore/tables/key.go
  • core/providers/azure/azure.go
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • transports/bifrost-http/handlers/providers.go
  • core/providers/azure/files.go
  • core/schemas/account.go
  • transports/bifrost-http/lib/config.go
  • framework/configstore/tables/key.go
  • core/providers/azure/azure.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/handlers/providers.go
  • transports/bifrost-http/lib/config.go
🧬 Code graph analysis (4)
transports/bifrost-http/handlers/providers.go (3)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
transports/bifrost-http/lib/config.go (1)
  • IsRedacted (3030-3053)
transports/bifrost-http/lib/config.go (5)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/utils.go (1)
  • Ptr (56-58)
framework/configstore/clientconfig.go (1)
  • EnvKeyInfo (26-32)
framework/configstore/tables/key.go (2)
core/schemas/account.go (1)
  • AzureKeyConfig (23-31)
ui/lib/types/config.ts (1)
  • AzureKeyConfig (23-30)
core/providers/azure/azure.go (6)
core/schemas/account.go (2)
  • Key (8-19)
  • AzureKeyConfig (23-31)
core/schemas/bifrost.go (2)
  • BifrostError (462-471)
  • Azure (36-36)
core/providers/utils/utils.go (1)
  • NewBifrostOperationError (733-744)
core/schemas/utils.go (2)
  • IsAnthropicModel (1048-1050)
  • Ptr (16-18)
core/utils.go (1)
  • Ptr (56-58)
core/providers/azure/types.go (1)
  • AzureAPIVersionDefault (4-4)
🪛 GitHub Actions: PR #1133
framework/configstore/tables/key.go

[error] 90-90: AzureKeyConfig: undefined: ClientID (type *schemas.AzureKeyConfig has no field or method ClientID).

🔇 Additional comments (9)
transports/bifrost-http/handlers/providers.go (1)

767-791: AzureKeyConfig redaction merge for ClientID/ClientSecret/TenantID is consistent and safe

The new preserve-on-redaction logic for client_id, client_secret, and tenant_id aligns with the existing Azure api_version handling: pointer checks are correct, comparisons use the redacted value, and restoring from oldRawKey.AzureKeyConfig avoids losing the original secrets when the UI sends masked values. I don’t see correctness or safety issues here.

core/schemas/account.go (1)

28-30: AzureKeyConfig schema extensions look correct

ClientID, ClientSecret, and TenantID are added as optional pointers with the expected JSON field names and comments, matching the rest of the stack (DB, config, UI). This will serialize cleanly and supports redaction.

framework/configstore/tables/key.go (1)

33-35: DB wiring for Azure and Bedrock key configs is consistent and symmetric

The added Azure columns (AzureClientID, AzureClientSecret, AzureTenantID) and Bedrock JSON columns are correctly mapped:

  • BeforeSave copies from the in-memory config into the DB fields with appropriate nil checks.
  • AfterFind reconstructs AzureKeyConfig and BedrockKeyConfig only when relevant columns are populated, mirroring the existing endpoint/api_version/deployments patterns.

This keeps the table representation and schema structs in sync without obvious nil or marshaling pitfalls.

Also applies to: 45-52, 83-110, 151-193, 211-219

transports/bifrost-http/lib/config.go (1)

2169-2196: Azure credential redaction now properly covers ClientID/ClientSecret/TenantID

The Azure redaction block correctly:

  • Emits env.VAR when an env mapping exists for client_id, client_secret, or tenant_id.
  • Otherwise masks values via RedactKey, so raw client secrets and IDs never leave the backend.

This brings Azure into line with Vertex/Bedrock redaction behavior and fixes the earlier clear‑text ClientSecret exposure.

core/providers/azure/files.go (1)

8-13: setAzureAuth correctly implements prioritized Azure auth with error propagation

This helper now:

  • Prefers service principal credentials via getOrCreateAuth and GetToken(DefaultAzureScope), falling back to a context token and then to api-key.
  • Returns a *schemas.BifrostError on failures rather than silently mutating headers, letting callers abort file/batch flows cleanly.

The header mutations (mutually exclusive Authorization vs api-key) and nil-token check look sound.

Please run an end‑to‑end test against Azure with: (1) only client_id/client_secret/tenant_id set, (2) only context token set, and (3) only api key set, to confirm the three paths behave as expected for file/batch APIs.

Also applies to: 15-56

core/providers/azure/azure.go (4)

14-20: Centralized Azure service principal support and credential caching look solid

The additions of DefaultAzureScope, the credentials sync.Map, getOrCreateAuth, and getAzureAuthHeaders cleanly encapsulate Azure auth:

  • Credentials are cached per tenantID:clientID, avoiding redundant NewClientSecretCredential calls.
  • getAzureAuthHeaders uniformly enforces the priority order (service principal → context token → API key) and returns typed *BifrostError on failure.

This is a good foundation for all Azure paths to share.

It would be worth validating against the Azure docs for client‑credentials auth to confirm DefaultAzureScope and ClientSecretCredential are the right choices for all supported Azure OpenAI endpoints.

Also applies to: 32-44, 46-114


170-183: completeRequest and listModelsByKey now align with centralized auth

Both completeRequest and listModelsByKey now:

  • Compute isAnthropicModel where relevant and obtain headers from getAzureAuthHeaders, so service principal / context / API key flows are shared.
  • Apply the returned header map directly to fasthttp.Request before building the Azure URL.

This removes inlined auth logic and keeps the surface consistent across text/chat/embedding and model-list operations.

Also applies to: 256-263


408-413: Streaming endpoints correctly adopt getAzureAuthHeaders

TextCompletionStream, ChatCompletionStream, ResponsesStream, and SpeechStream now all call getAzureAuthHeaders:

  • Anthropic paths pass isAnthropicModel=true so API-key fallback uses x-api-key, then add anthropic-version.
  • OpenAI-compatible Azure paths pass false and get api-key or Authorization as appropriate.
  • Each function short‑circuits and returns the *BifrostError from getAzureAuthHeaders on auth failure.

This keeps streaming auth behavior in sync with non‑streaming calls and with the service principal priority rules.

Also applies to: 548-552, 596-599, 736-739, 769-772, 914-918


1308-1310: File and batch APIs now surface Azure auth failures explicitly

All file/batch methods (FileUpload/List/Retrieve/Delete/Content and BatchCreate/List/Retrieve/Cancel) now:

  • Call the updated setAzureAuth and check its *schemas.BifrostError return.
  • Abort early on auth failures (including token acquisition problems) instead of sending a malformed unauthenticated request.

The resource cleanup paths (releasing requests/responses) remain correct around these new checks.

Also applies to: 1415-1417, 1521-1526, 1617-1622, 1744-1749, 1865-1867, 1986-1988, 2087-2092, 2185-2190

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants