Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/bedrock-static-keys-session-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@ai-sdk/amazon-bedrock': patch
---

fix(amazon-bedrock): do not merge AWS_SESSION_TOKEN from env with explicit access keys

When `accessKeyId` and `secretAccessKey` are both passed as options, session credentials now use only `options.sessionToken` or omit the token — avoiding workload tokens (e.g. EKS IRSA) invalidating SigV4 for static IAM user keys.

Docs: align Amazon Bedrock provider page with this behavior.
29 changes: 13 additions & 16 deletions content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,10 @@ const bedrock = createAmazonBedrock({
```

<Note>
The credentials settings fall back to environment variable defaults described
below. These may be set by your serverless environment without your awareness,
which can lead to merged/conflicting credential values and provider errors
around failed authentication. If you're experiencing issues be sure you are
explicitly specifying all settings (even if `undefined`) to avoid any
defaults.
Omitted options use the environment variables below. When **both**
`accessKeyId` and `secretAccessKey` are strings, SigV4 uses a **`sessionToken`
only if you pass one**—not `AWS_SESSION_TOKEN` from the environment—so static
keys are not mixed with workload tokens (e.g. EKS IRSA).
</Note>

You can use the following optional settings to customize the Amazon Bedrock provider instance:
Expand All @@ -160,8 +158,10 @@ You can use the following optional settings to customize the Amazon Bedrock prov

- **sessionToken** _string_

Optional. The AWS session token that you want to use for the API calls.
It uses the `AWS_SESSION_TOKEN` environment variable by default.
Optional. For temporary credentials. With **both** access keys set as strings,
pass the token here if needed; `AWS_SESSION_TOKEN` from the environment is not
used. If either key is taken from the environment, omitting `sessionToken`
allows `AWS_SESSION_TOKEN`.

- **credentialProvider** _() =&gt; Promise&lt;&#123; accessKeyId: string; secretAccessKey: string; sessionToken?: string; &#125;&gt;_

Expand Down Expand Up @@ -1359,8 +1359,10 @@ You can use the following optional settings to customize the Bedrock Anthropic p

- **sessionToken** _string_

Optional. The AWS session token that you want to use for the API calls.
It uses the `AWS_SESSION_TOKEN` environment variable by default.
Optional. For temporary credentials. With **both** access keys set as strings,
pass the token here if needed; `AWS_SESSION_TOKEN` from the environment is not
used. If either key is taken from the environment, omitting `sessionToken`
allows `AWS_SESSION_TOKEN`.

- **apiKey** _string_

Expand Down Expand Up @@ -1618,9 +1620,4 @@ dependency on the `@aws-sdk/client-bedrock-runtime` package.
The `bedrockOptions` provider setting previously available has been removed. If
you were using the `bedrockOptions` object, you should now use the `region`,
`accessKeyId`, `secretAccessKey`, and `sessionToken` settings directly instead.

Note that you may need to set all of these explicitly, e.g. even if you're not
using `sessionToken`, set it to `undefined`. If you're running in a serverless
environment, there may be default environment variables set by your containing
environment that the Amazon Bedrock provider will then pick up and could
conflict with the ones you're intending to use.
Static IAM user keys do not require `sessionToken`.
43 changes: 43 additions & 0 deletions packages/amazon-bedrock/src/bedrock-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,49 @@ describe('AmazonBedrockProvider', () => {
);
});

it('does not use AWS_SESSION_TOKEN from env when both access keys are passed as options', async () => {
mockLoadOptionalSetting.mockImplementation(
({ settingValue, environmentVariableName }) => {
if (environmentVariableName === 'AWS_BEARER_TOKEN_BEDROCK') {
return settingValue;
}
if (environmentVariableName === 'AWS_SESSION_TOKEN') {
return 'env-session-token-should-not-be-used';
}
return settingValue;
},
);

createAmazonBedrock({
region: 'us-east-1',
accessKeyId: 'from-options-ak',
secretAccessKey: 'from-options-sk',
});

const getCredentials = mockCreateSigV4FetchFunction.mock.calls[0][0];
await expect(getCredentials()).resolves.toMatchObject({
accessKeyId: 'from-options-ak',
secretAccessKey: 'from-options-sk',
sessionToken: undefined,
});
});

it('uses options.sessionToken when both access keys are passed as options', async () => {
mockLoadOptionalSetting.mockImplementation(() => undefined);

createAmazonBedrock({
region: 'us-east-1',
accessKeyId: 'from-options-ak',
secretAccessKey: 'from-options-sk',
sessionToken: 'explicit-session',
});

const getCredentials = mockCreateSigV4FetchFunction.mock.calls[0][0];
await expect(getCredentials()).resolves.toMatchObject({
sessionToken: 'explicit-session',
});
});

it('should work with credential provider when no API key is provided', () => {
// Mock loadOptionalSetting to return undefined (no API key)
mockLoadOptionalSetting.mockImplementation(() => undefined);
Expand Down
22 changes: 16 additions & 6 deletions packages/amazon-bedrock/src/bedrock-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ export interface AmazonBedrockProviderSettings {
secretAccessKey?: string;

/**
* The AWS session token to use for the Bedrock provider. Defaults to the value of the
* `AWS_SESSION_TOKEN` environment variable.
* The AWS session token to use for the Bedrock provider. When `accessKeyId` and
* `secretAccessKey` are both passed explicitly as options, only this field is used
* for the session token — **`AWS_SESSION_TOKEN` is not read from the environment**
* (so workload tokens from e.g. EKS IRSA are not mixed with static access keys).
* If either access key field is omitted and resolved from the environment, the
* session token also falls back to `AWS_SESSION_TOKEN` when not set here.
*/
sessionToken?: string;

Expand Down Expand Up @@ -221,10 +225,16 @@ export function createAmazonBedrock(
environmentVariableName: 'AWS_SECRET_ACCESS_KEY',
description: 'AWS secret access key',
}),
sessionToken: loadOptionalSetting({
settingValue: options.sessionToken,
environmentVariableName: 'AWS_SESSION_TOKEN',
}),
sessionToken:
typeof options.accessKeyId === 'string' &&
typeof options.secretAccessKey === 'string'
? typeof options.sessionToken === 'string'
? options.sessionToken
: undefined
: loadOptionalSetting({
settingValue: options.sessionToken,
environmentVariableName: 'AWS_SESSION_TOKEN',
}),
};
} catch (error) {
// Provide helpful error message for missing AWS credentials
Expand Down
Loading