feat(bedrock): support Bearer token auth for Converse API (#3125)
Adds bearer token authentication for the Bedrock Converse API, enabling users to authenticate with an API key instead of SigV4/IAM credentials. When a bearer token is available (via `options.bearerToken` or the `AWS_BEARER_TOKEN_BEDROCK` env var), the provider: 1. Sets dummy credentials to prevent SDK credential resolution errors 2. Injects middleware after SigV4 signing that replaces the Authorization header with `Bearer <token>` and removes SigV4-specific headers This uses the official `bedrock:CallWithBearerToken` IAM action, which is a documented AWS feature for API key auth on Bedrock endpoints. Use case: users who receive a Bedrock API key (bearer token) from the AWS console or their admin, without having IAM access keys or instance roles. Similar to how ANTHROPIC_API_KEY works for direct Anthropic API. Required IAM permission on the token's identity: bedrock:CallWithBearerToken Tested: Bearer token successfully authenticates against Bedrock Converse API (returns correct 403 for missing IAM permission, not auth format error). SigV4 path is unchanged when no bearer token is set.
This commit is contained in:
@@ -74,6 +74,12 @@ export interface BedrockOptions extends StreamOptions {
|
||||
* Tags appear in AWS Cost Explorer split cost allocation data.
|
||||
* @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStream.html */
|
||||
requestMetadata?: Record<string, string>;
|
||||
/** Bearer token for Bedrock API key authentication.
|
||||
* When set, bypasses SigV4 signing and sends Authorization: Bearer <token> instead.
|
||||
* Requires `bedrock:CallWithBearerToken` IAM permission on the token's identity.
|
||||
* Set via AWS_BEARER_TOKEN_BEDROCK env var or pass directly.
|
||||
* @see https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonbedrock.html */
|
||||
bearerToken?: string;
|
||||
}
|
||||
|
||||
type Block = (TextContent | ThinkingContent | ToolCall) & { index?: number; partialJson?: string };
|
||||
@@ -110,6 +116,9 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOpt
|
||||
profile: options.profile,
|
||||
};
|
||||
|
||||
// Resolve bearer token for API key auth (bypasses SigV4)
|
||||
const bearerToken = options.bearerToken || process.env.AWS_BEARER_TOKEN_BEDROCK || undefined;
|
||||
|
||||
// in Node.js/Bun environment only
|
||||
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
||||
// Region resolution: explicit option > env vars > SDK default chain.
|
||||
@@ -130,6 +139,15 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOpt
|
||||
};
|
||||
}
|
||||
|
||||
// Bearer token auth: use API key instead of SigV4 signing.
|
||||
// Requires bedrock:CallWithBearerToken IAM permission.
|
||||
if (bearerToken && process.env.AWS_BEDROCK_SKIP_AUTH !== "1") {
|
||||
config.credentials = {
|
||||
accessKeyId: "bearer-token-auth",
|
||||
secretAccessKey: "bearer-token-auth",
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
process.env.HTTP_PROXY ||
|
||||
process.env.HTTPS_PROXY ||
|
||||
@@ -164,6 +182,22 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream", BedrockOpt
|
||||
try {
|
||||
const client = new BedrockRuntimeClient(config);
|
||||
|
||||
// Inject bearer token middleware after SigV4 signing
|
||||
if (bearerToken) {
|
||||
client.middlewareStack.addRelativeTo(
|
||||
(next) => async (args: any) => {
|
||||
if (args.request?.headers) {
|
||||
args.request.headers["authorization"] = `Bearer ${bearerToken}`;
|
||||
delete args.request.headers["x-amz-date"];
|
||||
delete args.request.headers["x-amz-security-token"];
|
||||
delete args.request.headers["x-amz-content-sha256"];
|
||||
}
|
||||
return next(args);
|
||||
},
|
||||
{ relation: "after", toMiddleware: "awsAuthMiddleware", name: "bearerTokenAuth" },
|
||||
);
|
||||
}
|
||||
|
||||
const cacheRetention = resolveCacheRetention(options.cacheRetention);
|
||||
let commandInput = {
|
||||
modelId: model.id,
|
||||
|
||||
Reference in New Issue
Block a user