A collection of credential providers for AWS SDK, enabling authentication across different AWS environments and services
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Custom credential chain functionality allows building flexible credential provider sequences that try multiple credential sources in order, with automatic expiration and refresh capabilities.
Creates a custom credential provider chain from multiple credential providers.
/**
* Creates a credential chain from multiple credential providers that are tried in sequence
* @param credentialProviders - One or more credential providers to chain together
* @returns Chainable credential provider with expiration control
*/
function createCredentialChain(
...credentialProviders: RuntimeConfigAwsCredentialIdentityProvider[]
): RuntimeConfigAwsCredentialIdentityProvider & CustomCredentialChainOptions;
interface CustomCredentialChainOptions {
/** Sets credential expiration time to force refresh after specified milliseconds */
expireAfter(milliseconds: number): AwsCredentialIdentityProvider & CustomCredentialChainOptions;
}Usage Examples:
import { S3Client } from "@aws-sdk/client-s3";
import {
createCredentialChain,
fromEnv,
fromIni,
fromInstanceMetadata
} from "@aws-sdk/credential-providers";
// Basic credential chain
const client = new S3Client({
region: "us-east-1",
credentials: createCredentialChain(
fromEnv(),
fromIni(),
fromInstanceMetadata()
)
});
// Chain with custom expiration
const expiringClient = new S3Client({
region: "us-east-1",
credentials: createCredentialChain(
fromEnv(),
fromIni({ profile: "default" })
).expireAfter(15 * 60 * 1000) // 15 minutes
});
// Complex chain with multiple profiles and sources
const complexClient = new S3Client({
region: "us-east-1",
credentials: createCredentialChain(
fromEnv(),
fromIni({ profile: "development" }),
fromIni({ profile: "default" }),
fromInstanceMetadata()
)
});Credential chains follow this execution pattern:
import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
const chainWithLogging = createCredentialChain(
fromEnv({ logger: console }), // Try environment variables first
fromIni({
profile: "backup-profile",
logger: console
}) // Fallback to INI file
);
// This will:
// 1. Try environment variables
// 2. If that fails, try the backup-profile from INI
// 3. If both fail, throw the last errorMix existing providers with custom credential functions:
import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
// Custom credential function
async function fromCustomSource(): Promise<AwsCredentialIdentity> {
// Fetch credentials from your custom source
// e.g., corporate credential management system, vault, etc.
const response = await fetch("https://internal-auth.company.com/credentials");
const data = await response.json();
return {
accessKeyId: data.accessKey,
secretAccessKey: data.secretKey,
sessionToken: data.sessionToken,
expiration: new Date(data.expiresAt)
};
}
// Create chain with custom provider
const client = new S3Client({
region: "us-east-1",
credentials: createCredentialChain(
fromEnv(),
fromCustomSource,
fromIni()
)
});Set automatic credential expiration to force periodic refresh:
import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
// Credentials expire after 30 minutes
const thirtyMinuteCredentials = createCredentialChain(
fromEnv(),
fromIni()
).expireAfter(30 * 60 * 1000);
// Minimum expiration is 5 minutes
try {
const tooShort = createCredentialChain(fromEnv()).expireAfter(60 * 1000); // 1 minute
} catch (error) {
console.error(error.message);
// "@aws-sdk/credential-providers - createCredentialChain(...).expireAfter(ms) may not be called with a duration lower than five minutes."
}Apply shared initialization properties to all providers in the chain:
import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
// Shared configuration
const sharedInit = {
logger: console,
clientConfig: {
maxAttempts: 3,
requestTimeout: 10000
}
};
const client = new S3Client({
region: "us-east-1",
credentials: createCredentialChain(
fromEnv(sharedInit),
fromIni({
...sharedInit,
profile: "development"
})
)
});Create different chains for different environments:
import {
createCredentialChain,
fromEnv,
fromIni,
fromInstanceMetadata,
fromContainerMetadata
} from "@aws-sdk/credential-providers";
function createCredentialsForEnvironment(environment: string) {
switch (environment) {
case "development":
return createCredentialChain(
fromEnv(),
fromIni({ profile: "dev" })
);
case "testing":
return createCredentialChain(
fromEnv(),
fromIni({ profile: "test" })
);
case "production":
return createCredentialChain(
fromInstanceMetadata(), // EC2 instances
fromContainerMetadata(), // ECS containers
fromEnv() // Fallback to environment
);
default:
return createCredentialChain(
fromEnv(),
fromIni()
);
}
}
const client = new S3Client({
region: "us-east-1",
credentials: createCredentialsForEnvironment(process.env.NODE_ENV || "development")
});Handle chain failures and debug credential resolution:
import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
const debugChain = createCredentialChain(
fromEnv({ logger: console }),
fromIni({
profile: "nonexistent",
logger: console
})
);
try {
const credentials = await debugChain();
console.log("Credentials resolved successfully");
} catch (error) {
console.error("All credential providers in chain failed:");
console.error("Final error:", error.message);
// Check specific error types
if (error.name === "ProviderError") {
console.error("No providers in chain succeeded");
}
}import { createCredentialChain, fromEnv, fromIni, fromInstanceMetadata } from "@aws-sdk/credential-providers";
function createAdaptiveChain() {
const providers = [fromEnv()];
// Add profile-based provider if profile is available
if (process.env.AWS_PROFILE) {
providers.push(fromIni({ profile: process.env.AWS_PROFILE }));
}
// Add metadata provider if running on AWS
if (process.env.AWS_EXECUTION_ENV || process.env.AWS_LAMBDA_FUNCTION_NAME) {
providers.push(fromInstanceMetadata());
}
return createCredentialChain(...providers);
}import { createCredentialChain, fromEnv, fromIni } from "@aws-sdk/credential-providers";
function withRetry<T extends (...args: any[]) => any>(fn: T, maxRetries = 3): T {
return (async (...args: any[]) => {
let lastError;
for (let i = 0; i <= maxRetries; i++) {
try {
return await fn(...args);
} catch (error) {
lastError = error;
if (i < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
}
}
}
throw lastError;
}) as T;
}
const resilientChain = createCredentialChain(
withRetry(fromEnv()),
withRetry(fromIni())
);expireAfter() judiciously to balance security and performance