Skip to content

[codex] Add AWS-native authentication for Bedrock#1938

Open
HAYDEN-OAI wants to merge 12 commits into
mainfrom
dev/hayden/bedrock-provider-auth
Open

[codex] Add AWS-native authentication for Bedrock#1938
HAYDEN-OAI wants to merge 12 commits into
mainfrom
dev/hayden/bedrock-provider-auth

Conversation

@HAYDEN-OAI

@HAYDEN-OAI HAYDEN-OAI commented Jun 12, 2026

Copy link
Copy Markdown

Summary

This adds first-class Amazon Bedrock support through the standard OpenAI client:

import OpenAI from 'openai';
import { bedrock } from 'openai/providers/bedrock';

const client = new OpenAI({
  provider: bedrock({ region: 'us-west-2' }),
});

The change:

  • introduces an internal provider seam so third-party providers can own routing and final request authentication
  • adds a Bedrock provider with bearer-token and AWS SigV4 authentication
  • keeps BedrockOpenAI working as a compatibility wrapper
  • packages the provider as openai/providers/bedrock for CommonJS, ESM, browser bearer use, and JSR

Provider seam

When provider is configured, the provider owns the base URL and authentication. The client rejects conflicting top-level apiKey, adminAPIKey, workloadIdentity, and baseURL options and does not inherit ambient OpenAI credentials or headers.

The provider receives the fully serialized request after subclass preparation and before every request attempt. This lets Bedrock sign the exact method, URL, headers, query, and body while refreshing credentials and signatures on retries. withOptions() preserves the provider configuration.

Bedrock routing and authentication

The provider uses the regional Mantle endpoint:

https://bedrock-mantle.<region>.api.aws/openai/v1

The /openai/v1 prefix is intentional. AWS confirmed that it is the OpenAI compatibility contract, while similarly named routes under /v1, including models, can return different response shapes. Requests are signed with the bedrock-mantle SigV4 service name.

Authentication is selected in this order:

  1. an explicit bearer token, token provider, static AWS credentials, AWS profile, or credential provider
  2. AWS_BEARER_TOKEN_BEDROCK
  3. the standard AWS credential chain

Explicit bearer and AWS credential modes are mutually exclusive. Passing apiKey: null skips an ambient Bedrock bearer token and deliberately selects AWS credentials.

Bearer authentication has no additional runtime dependencies. SigV4 authentication is supported in Node.js and compatible server runtimes through these optional peer dependencies:

  • @aws-sdk/credential-provider-node
  • @smithy/hash-node
  • @smithy/signature-v4

The dependencies load only when AWS credential authentication is selected. Their ESM and CommonJS resolution is module-relative rather than working-directory-relative, and the browser bundle can import the provider for bearer authentication without bundling AWS packages.

SigV4 signs the exact serialized, replayable request body and runs again for every retry. The provider also:

  • validates canonical endpoint and signing-region agreement
  • preserves repeated query parameters
  • signs the transmitted uppercase HTTP method
  • rejects conflicting custom Authorization headers
  • disables automatic redirects for signed requests
  • redacts AWS session tokens from request logs

Request streaming through UNSIGNED-PAYLOAD or AWS-chunked signing is intentionally outside this first milestone. Standard JSON requests are replayable, response streaming is unaffected, and Mantle waits for the complete request body before authentication and authorization.

Compatibility and packaging

BedrockOpenAI remains available with awsRegion, awsProfile, awsCredentialProvider, and bedrockTokenProvider option names. It now delegates to the same provider implementation, including credential refresh and withOptions() behavior.

This also:

  • updates the README, Bedrock guide, and example to prefer the provider API
  • exports the provider through npm and JSR
  • adds CommonJS, ESM, and mixed-module build smoke tests
  • verifies bearer authentication in the browser bundle without AWS dependencies
  • preserves response.output_text for ordinary, non-structured Responses API calls

Testing

The tests cover provider ownership, ambient OpenAI configuration isolation, request preparation order, retry signing, bearer and AWS credential precedence, the real AWS environment credential chain with a temporary session token, credential refresh, withOptions(), endpoint normalization, region validation, custom authorization rejection, non-replayable body rejection, browser bearer authentication, compatibility behavior, and a deterministic SigV4 fixture.

The focused suites include 94 tests. V8 coverage across the ordinary and dependency-mocking suites is:

  • src/internal/provider.ts: 100% statements, branches, functions, and lines
  • src/providers/bedrock.ts: 100% statements, functions, and lines; 98.85% branches
  • src/bedrock.ts: 100% statements, branches, functions, and lines
  • all changed executable statements in the shared client, request logger, and Responses parser: 100%

Live validation is isolated from the standard test suite under tests/live/bedrock.live.test.ts. It requires an explicit safety flag, disables retries, uses store: false, and can exercise bearer, environment bearer, default-chain, named-profile, static, and custom-provider authentication:

BEDROCK_LIVE_TEST=1 \
BEDROCK_LIVE_AUTH=profile \
AWS_PROFILE=my-profile \
AWS_REGION=us-west-2 \
BEDROCK_MODEL=openai.gpt-oss-120b \
pnpm test:live:bedrock

Set BEDROCK_LIVE_STREAM=1 to include a streaming request. AWS_BEDROCK_BASE_URL can override the derived endpoint for live endpoint comparisons.

Attribution

This builds on and substantially expands Jim's initial implementation in jim-openai/openai-node#1. Thank you, Jim, for getting the first version moving and letting us take it over.

Validation

  • 94 focused Jest tests
  • frozen pnpm install and full 1,103-test Jest suite
  • focused V8 coverage for the provider seam, Bedrock provider, compatibility wrapper, and shared-client changes
  • SDK build, including CommonJS, ESM, and mixed-module SigV4 smoke tests
  • ESLint and Prettier
  • browser Webpack build
  • Are The Types Wrong? package check
  • Publint
  • JSR publish dry run
  • live static SigV4 validation with model discovery and Responses inference
  • second-region live validation in us-east-2
  • upstream CI

The full pnpm lint pipeline, including formatting, ESLint, SDK and Deno builds, TypeScript, Are The Types Wrong?, Publint, and the JSR publish dry run, passes locally.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce11aa0085

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/client.ts
Comment thread package.json Outdated
Comment thread package.json Outdated
Comment thread README.md
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.

3 participants