Skip to content

feat(ai): resolve Bedrock credentials through the AWS default chain - #47436

Merged
rekram1-node merged 4 commits into
v2from
bedrock-auth
Sep 5, 2026
Merged

rekram1-node merged 4 commits into
v2from
bedrock-auth

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Sep 5, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The native Bedrock routes in packages/ai only accepted a static { accessKeyId, secretAccessKey, sessionToken } struct or a bearer apiKey. Nothing read AWS_PROFILE, ~/.aws shared config, the SSO cache, web identity tokens, or instance/container metadata, and STS-vended credentials could not refresh because they were captured once at configure(). V1 delegated all of this to the AI SDK's credentialProvider; V2 dropped the AI SDK for Bedrock but never replaced that layer.

Changes

  • BedrockAuth.sigV4 accepts a CredentialSource (static or Effect<Credentials>) resolved before every request.
  • BedrockAuth.defaultChain({ region, profile? }) lazily imports @aws-sdk/credential-providers and runs a fresh fromNodeProviderChain on every request. The SDK memoizes credentials that carry no expiration for the life of the provider, which pinned shared-config keys rotated on disk by SSO tooling (fix(core): Bedrock SDK/language model cache has no TTL — STS tokens expire mid-session #30940); a per-request chain always re-reads them. Mirrors the Vertex ADC pattern in google-vertex-shared.ts.
  • BedrockAuth.resolveAuth centralizes precedence for Converse and Mantle: apiKey ?? AWS_BEARER_TOKEN_BEDROCK (bearer) → explicit static credentials → default chain. auth: "sigv4" in settings ignores an ambient bearer token.
  • BedrockAuth.resolveRegion: region ?? credentials.region ?? AWS_REGION ?? AWS_DEFAULT_REGION ?? us-east-1, applied to both the endpoint host and the SigV4 scope (Converse previously let them diverge).
  • Settings/Config gain profile; auth: "bearer" | "sigv4" moves onto Config so programmatic callers can also opt out of the ambient bearer token. model(id, settings) is now just configure(settings).model(id).
  • Root dev script drops --conditions=browser: it resolves @smithy/core/config to a browser build that stubs node-only exports and breaks the credential chain (parseKnownFiles is not a function). The release build already uses node conditions.
  • @aws-sdk/credential-providers added to packages/ai.

Chain failures surface as AIError with an Authentication reason.

Tests

  • Chain failure → Authentication error (uses a missing profile with IMDS disabled so it is deterministic on any machine).
  • Chain success via AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN for Converse and Mantle, asserting the SigV4 credential scope and x-amz-security-token.
  • Rotated credentials are picked up on the next request against the same model instance.
  • AWS_BEARER_TOKEN_BEDROCK precedence, auth: "sigv4" ignoring it, region env fallbacks, and static credentials taking the configured region for the scope.
  • New test/lib/env.ts helper scopes process.env overrides (needed because the AWS SDK reads process.env directly).

Follow-up (separate PR, packages/core)

Wire discovery into AmazonBedrockPlugin: narrow the models.dev env method to AWS_BEARER_TOKEN_BEDROCK so AWS_ACCESS_KEY_ID stops being sent as a bearer token, flip activation to enabled when chain-style env is present, forward profile through mapBedrockSettings, and delete the dead AI SDK hooks plus the @ai-sdk/amazon-bedrock dependency.

Bedrock routes only accepted static SigV4 credentials or a bearer apiKey,
so SSO, shared-config profiles, web identity, and instance credentials were
unusable and STS-vended credentials could not refresh.

- SigV4 auth accepts an Effect credential source resolved per request
- BedrockAuth.defaultChain lazily loads @aws-sdk/credential-providers and
  memoizes fromNodeProviderChain so the SDK owns caching and refresh
- Facades fall back to AWS_BEARER_TOKEN_BEDROCK, then static credentials,
  then the default chain; region falls back to AWS_REGION and
  AWS_DEFAULT_REGION and is applied to the SigV4 scope
- Settings accept profile for the default chain; auth: sigv4 ignores an
  ambient bearer token
Memoizing fromNodeProviderChain per model pinned shared-config credentials
without an expiration for the process lifetime, so keys rotated on disk by
SSO tooling were never re-read. Build the chain per request instead so the
default chain always reflects the current on-disk and environment state.
Browser conditions resolve @smithy/core/config to its browser build, which
stubs node-only exports and breaks the AWS credential chain with
"parseKnownFiles is not a function". The release build already uses the
default node conditions.
Only Settings could request sigv4 to ignore an ambient
AWS_BEARER_TOKEN_BEDROCK, leaving programmatic configure callers without a
way to opt out. Move the mode and its validation onto Config so both paths
share one constructor.
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.

1 participant