Skip to content

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

Open
HAYDEN-OAI wants to merge 14 commits into
nextfrom
dev/hayden/bedrock-provider-auth
Open

[codex] Add AWS-native authentication for Bedrock#1938
HAYDEN-OAI wants to merge 14 commits into
nextfrom
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 and a dedicated AWS entrypoint:

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

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 Bedrock bearer-token and AWS SigV4 authentication
  • keeps the existing bearer-only BedrockOpenAI compatibility class unchanged
  • separates the dependency-free bearer entrypoint from the statically analyzable AWS entrypoint
  • packages both entrypoints 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 when switching from the OpenAI route to a provider.

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.

Provider factories capture immutable configuration, while every OpenAI client gets fresh runtime state. An opaque provider registry prevents arbitrary JavaScript objects from impersonating providers and uses a globalThis symbol plus WeakMap so providers work across duplicate CommonJS and ESM module instances without retaining discarded configurations.

withOptions() preserves provider-owned headers when cloning the same provider. It drops inherited OpenAI organization, project, and custom headers only when crossing from the core OpenAI route to a provider or switching provider objects.

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.

The AWS entrypoint selects authentication 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.

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.

Packaging

Bearer authentication is available from openai/providers/bedrock without AWS dependencies. This keeps normal openai imports, the legacy BedrockOpenAI class, and browser bearer bundles independent from AWS packages.

AWS credential authentication is available from openai/providers/bedrock/aws. It uses normal static imports so Vite, Webpack, Vercel-style file tracing, and other serverless packagers can discover:

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

These remain optional peer dependencies for the package as a whole, but are required before importing the /aws entrypoint. If one is absent, import fails immediately with the runtime's normal module-not-found error.

The AWS subpath is exported from npm and JSR. The standalone Bedrock guide remains in the repository rather than being added to build distributions, consistent with other provider guides.

Compatibility

The existing BedrockOpenAI class remains bearer-only and available for current applications. New AWS-authenticated applications should use new OpenAI({ provider: bedrock(...) }) from openai/providers/bedrock/aws.

The shared Responses parser also restores the SDK-synthesized output_text convenience property when a raw streamed final response omits it. The underlying distinction between raw wire response types and SDK-enriched response types is broader schema work and is not expanded in this PR.

Testing

The focused suites cover provider ownership, ambient OpenAI configuration isolation, same-provider cloning, request preparation order, retry signing, bearer and AWS credential precedence, the real AWS environment credential chain with a temporary session token, credential refresh, endpoint normalization, region validation, custom authorization rejection, non-replayable body rejection, browser bearer authentication, dependency isolation, compatibility behavior, and a deterministic SigV4 fixture clearly marked with AWS documentation test credentials.

V8 coverage across the four provider implementation modules is:

  • 100% statements
  • 99.36% branches
  • 100% functions
  • 100% lines

Live validation remains 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

  • 61 focused provider tests and 78 provider/compatibility tests
  • full 1,092-test Jest suite
  • focused V8 coverage for the provider registry and both Bedrock entrypoints
  • full lint pipeline: Prettier, ESLint, SDK and Deno builds, TypeScript, Are The Types Wrong?, Publint, and JSR publish dry run
  • browser Webpack build with the dependency-free bearer entrypoint
  • Vite 7 SSR build with noExternal across OpenAI, AWS SDK, and Smithy packages
  • Vercel Node File Trace verification of the packed AWS entrypoint and all three direct AWS dependencies
  • live static SigV4 validation with model discovery and Responses inference
  • second-region live validation in us-east-2

@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
@RowanAldean

Copy link
Copy Markdown

When can we expect this in Pi (such that we can start using OpenAI Models via Bedrock?)

Comment thread tests/fixtures/bedrock/v1/sigv4.json
Comment thread examples/bedrock/responses.ts
Comment thread README.md Outdated
Comment thread src/lib/ResponsesParser.ts
Comment thread scripts/build Outdated
Comment thread scripts/build Outdated
Comment thread scripts/build-deno Outdated
Comment thread src/internal/provider.ts
Comment thread src/client.ts Outdated
Comment thread src/providers/bedrock.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

upstream Needs to be addressed in Stainless upstream

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants