Skip to content

[Duplicate Code] Provider auth header construction is repeated across API proxy adapters #5620

Description

@github-actions

Duplicate Code Opportunity

Summary

  • Pattern: Each API proxy provider adapter hand-builds validation/model/request auth headers, including static credentials, OIDC fallback, unavailable-token handling, and provider-specific extras.
  • Locations: containers/api-proxy/providers/openai.js, anthropic.js, copilot.js, and gemini.js.
  • Impact: More than two copies on the security-critical credential-injection path. The shared createProviderOidcAuth helper reduces setup duplication, but auth header construction and fallback semantics still remain scattered. This overlaps with the completed prior provider scaffolding finding [Duplicate Code] Provider adapter credential scaffolding is repeated across API proxy providers #5197, but the pattern still reproduces.

Evidence

OpenAI defines static header construction and OIDC/static fallback locally:

75  function buildStaticAuthHeaders(key) {
76    if (customAuthHeader) {
77      return { [customAuthHeader]: key };
78    }
79    return { 'Authorization': `Bearer ${key}` };
80  }
...
107    getAuthHeaders() {
108      return resolveAuthHeaders(
109        (token) => (customAuthHeader
110          ? { [customAuthHeader]: token }
111          : { 'Authorization': ['Bearer', token].join(' ') }),
112        buildStaticAuthHeaders(apiKey),
113      );
114    },

Anthropic repeats OIDC readiness/static fallback for validation, model fetch, and request headers:

130    validationHeaders: () => {
131      if (oidcProvider && oidcProvider.isReady()) {
132        return {
133          'Authorization': `Bearer ${oidcProvider.getToken()}`,
134          'anthropic-version': '2023-06-01',
135          'content-type': 'application/json',
136        };
137      }
138      return {
139        [authHeaderName]: apiKey,
140        'anthropic-version': '2023-06-01',
141        'content-type': 'application/json',
142      };
143    },
...
177    getAuthHeaders(req) {
178      const oidcHeaders = resolveOidcAuthHeaders({
179        oidcProvider,
180        awsOidcProvider: null,
181        buildOidcHeaders: (token) => ({ 'Authorization': 'Bearer ' + token }),
182      });
...
192      const headers = oidcHeaders !== null ? { ...oidcHeaders } : { [authHeaderName]: apiKey };

Copilot repeats request-path-specific auth prefix selection plus OIDC/static fallback:

240      const oidcHeaders = resolveOidcAuthHeaders({
241        oidcProvider,
242        awsOidcProvider,
243        buildOidcHeaders: (token) => ({
244          'Authorization': ['Bearer', token].join(' '),
245          'Copilot-Integration-Id': integrationId,
246        }),
247      });
248      if (oidcHeaders !== null) {
249        return oidcHeaders;
250      }
...
253      const authPrefix = (requiresGitHubTokenPrefix && !apiKey) ? 'token' : 'Bearer';
254      return {
255        ...(apiKey ? byokExtraHeaders : {}),
256        'Authorization': [authPrefix, authToken].join(' '),
257        'Copilot-Integration-Id': integrationId,
258      };

Gemini is simpler but still hand-codes the same three surfaces for one credential header:

43    validationPath: '/v1beta/models',
44    validationHeaders: () => ({ 'x-goog-api-key': apiKey }),
45    modelsPath: '/v1beta/models',
46    modelsFetchHeaders: () => ({ 'x-goog-api-key': apiKey }),
...
54    getAuthHeaders() {
55      return { 'x-goog-api-key': apiKey };
56    },

Suggested Refactoring

Add a small auth-header strategy abstraction, for example createAuthHeaderStrategy({ staticHeader, oidcHeader, extraHeaders, unavailableBehavior }), and let provider adapters supply only provider-specific constants and request predicates. Reuse it for validation headers, model fetch headers, and per-request headers so OIDC not-ready behavior and static-key fallback are implemented once.

Affected Files

  • containers/api-proxy/providers/openai.js — lines 75-114
  • containers/api-proxy/providers/anthropic.js — lines 130-192
  • containers/api-proxy/providers/copilot.js — lines 240-258
  • containers/api-proxy/providers/gemini.js — lines 43-56

Effort Estimate

Medium


Detected by Duplicate Code Detector workflow. Run date: 2026-06-27

Generated by Duplicate Code Detector · 161 AIC · ⊞ 23.1K ·

  • expires on Jul 27, 2026, 9:59 PM UTC

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions