Credentials

In order to authenticate requests, AWS services require you to provide your AWS access keys, also known as your AWS access key ID and secret access key. In the AWS SDK for PHP, these access keys are often referred to collectively as your credentials. This guide demonstrates how to provide your credentials to the AWS SDK for SDK using one of the following methods:

  1. Using credentials from environment variables
  2. Using IAM roles for Amazon EC2 instances
  3. Using IAM roles for Amazon EC2 Container Service Tasks
  4. Using the AWS credentials file and credential profiles
  5. Using hard-coded credentials
  6. Using a credential provider
  7. Using temporary credentials from AWS STS
  8. Using Assume Role Credentials

In general, it is recommended that you use IAM roles when running your application on Amazon EC2 and use credential profiles or environment variables elsewhere. Regardless of how you supply credentials to the SDK, it is encouraged that you follow the IAM Best Practices when managing your credentials.

Using credentials from environment variables

If you do not provide credentials to a client object at the time of its instantiation, the SDK will attempt to find credentials in your environment. The first place the SDK will check for credentials is in your environment variables. The SDK will use the getenv() function function to look for the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables. These credentials are referred to as environment credentials.

Using IAM roles for Amazon EC2 instances

Using IAM roles is the preferred technique for providing credentials to applications running on Amazon EC2. IAM roles remove the need to worry about credential management from your application. They allow an instance to "assume" a role by retrieving temporary credentials from the EC2 instance's metadata server. These temporary credentials, often referred to as instance profile credentials, allow access to the actions and resources that the role's policy allows.

When launching an EC2 instance, you can choose to associate it with an IAM role. Any application running on that EC2 instance is then allowed to assume the associated role. Amazon EC2 handles all the legwork of securely authenticating instances to the IAM service to assume the role and periodically refreshing the retrieved role credentials, keeping your application secure with almost no work on your part.

If you do not explicitly provide credentials to the client object and no environment variable credentials are available, the SDK attempts to retrieve instance profile credentials from an Amazon EC2 instance metadata server. These credentials are available only when running on Amazon EC2 instances that have been configured with an IAM role.

Note

Instance profile credentials and other temporary credentials generated by the AWS Security Token Service (AWS STS) are not supported by every service. Please check if the service you are using supports temporary credentials by reading AWS Services that Support AWS STS.

To Avoid hitting metadata service every time, an instance of Aws\CacheInterface can be passed in as the 'credentials' option to a client constructor. This lets SDK use cached instance profile credentials instead. For more information, see 'credentials' option.

For more information, see IAM Roles for Amazon EC2.

Using IAM roles for Amazon EC2 Container Service Tasks

With IAM roles for Amazon ECS tasks, you can specify an IAM role that can be used by the containers in a task. This provides a strategy for managing credentials for your applications to use, similar to the way that Amazon EC2 instance profiles provide credentials to EC2 instances.

Instead of creating and distributing your AWS credentials to the containers or using the EC2 instance’s role, you can associate an IAM role with an ECS task definition or RunTask API operation.

Note

Instance profile credentials and other temporary credentials generated by the AWS Security Token Service (AWS STS) are not supported by every service. Please check if the service you are using supports temporary credentials by reading AWS Services that Support AWS STS.

For more information, see IAM Roles for Amazon EC2 Container Service Tasks.

Using Assume Role Credentials

Using Aws\Credentials\AssumeRoleCredentialProvider to create credentials by assuming a role, you would need to provide 'client' information with a StsClient object and 'assume_role_params' details.

For more information regarding 'assume_role_params', see AssumeRole.

$assumeRoleCredentials = new AssumeRoleCredentialProvider([
    'client' => new StsClient([
        'region' => 'us-west-2',
        'version' => '2011-06-15'
    ]),
    'assume_role_params' => [
        'RoleArn' => '<string>', // REQUIRED
        'RoleSessionName' => '<string>', // REQUIRED
        ...
    ]
]);

Using the AWS credentials file and credential profiles

Starting with the AWS SDK for PHP version 2.6.2, you can use an AWS credentials file to specify your credentials. This is a special, INI-formatted file stored under your HOME directory, and is a good way to manage credentials for your development environment. The file should be placed at ~/.aws/credentials, where ~ represents your HOME directory.

Using an AWS credentials file offers a few benefits:

  1. Your projects' credentials are stored outside of your projects, so there is no chance of accidentally committing them into version control.
  2. You can define and name multiple sets of credentials in one place.
  3. You can easily reuse the same credentials between projects.
  4. Other AWS SDKs and tools support, or will soon support, this same credentials file. This allows you to reuse your credentials with other tools.

The format of the AWS credentials file should look something like the following:

[default]
aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID
aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEY

[project1]
aws_access_key_id = ANOTHER_AWS_ACCESS_KEY_ID
aws_secret_access_key = ANOTHER_AWS_SECRET_ACCESS_KEY

Each section (e.g., [default], [project1]), represents a separate credential profile. Profiles can be referenced from a SDK configuration file, or when you are instantiating a client, using the profile option:

<?php

use Aws\DynamoDb\DynamoDbClient;

// Instantiate a client with the credentials from the project1 profile
$client = new DynamoDbClient([
    'profile' => 'project1',
    'region'  => 'us-west-2',
    'version' => 'latest'
]);

If no credentials or profiles were explicitly provided to the SDK and no credentials were defined in environment variables, but a credentials file is defined, the SDK will use the "default" profile. You can change the default profile by specifying an alternate profile name in the AWS_PROFILE environment variable.

Using hard-coded credentials

You can provide hard-coded credentials to a SDK client by providing the "key", "secret", and optional "token" key value pairs to the "credentials" option of a client constructor.

$s3Client = new S3Client([
    'version'     => 'latest',
    'region'      => 'us-west-2',
    'credentials' => [
        'key'    => 'my-access-key-id',
        'secret' => 'my-secret-access-key',
    ],
]);

Warning

Hard-coding your credentials can be dangerous, because it is easy to accidentally commit your credentials into an SCM repository, potentially exposing your credentials to more people than intended. It can also make it difficult to rotate credentials in the future.

Using a credential provider

A credential provider is a function that returns a GuzzleHttp\Promise\PromiseInterface that is fulfilled with an Aws\Credentials\CredentialsInterface instance or rejected with an Aws\Exception\CredentialsException. You can use credential providers to implement your own custom logic for creating credentials or to optimize credential loading.

Credential providers are passed into the credentials client constructor option. Credential providers are asynchronous, which forces them to be lazily evaluated each time an API operation is invoked. As such, passing in a credential provider function to an SDK client constructor will not immediately validate the credentials. If the credential provider does not return a credentials object, an API operation will be rejected with an Aws\Exception\CredentialsException.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;

// Use the default credential provider
$provider = CredentialProvider::defaultProvider();

// Pass the provider to the client.
$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => $provider
]);

The SDK ships with several built-in providers that can be combined together along with any custom providers.

Important

Credential providers are invoked every time an API operation is performed. If loading credentials is an expensive task (e.g., loading from disk or a network resource) or if credentials are not cached by your provider, then you should consider wrapping your credential provider in an Aws\Credentials\CredentialProvider::memoize function. The default credential provider used by the SDK is automatically memoized.

env provider

Aws\Credentials\CredentialProvider::env attempts to load credentials from environment variables.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => CredentialProvider::env()
]);

ini provider

Aws\Credentials\CredentialProvider::ini attempts to load credentials from an ini credential file. The SDK will by default attempt to load the "default" profile from a file located at ~/.aws/credentials.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;

$provider = CredentialProvider::ini();
// Cache the results in a memoize function to avoid loading and parsing
// the ini file on every API operation.
$provider = CredentialProvider::memoize($provider);

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => $provider
]);

You can use a custom profile or ini file location by providing arguments to the function that creates the provider.

$profile = 'production';
$path = '/full/path/to/credentials.ini';

$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => $provider
]);

instanceProfile provider

Aws\Credentials\CredentialProvider::instanceProfile attempts to load credentials from Amazon EC2 instance profiles.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;

$provider = CredentialProvider::instanceProfile();
// Be sure to memoize the credentials
$memoizedProvider = CredentialProvider::memoize($provider);

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => $memoizedProvider
]);

ecsCredentials provider

Aws\Credentials\CredentialProvider::ecsCredentials attempts to load credentials by a GET request, whose uri is specified by environment variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI in the container.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;

$provider = CredentialProvider::ecsCredentials();
// Be sure to memoize the credentials
$memoizedProvider = CredentialProvider::memoize($provider);

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => '2006-03-01',
    'credentials' => $memoizedProvider
]);

defaultProvider provider

Aws\Credentials\CredentialProvider::defaultProvider is the default credential provider. This provider is used if you omit a credentials option when creating a client. It first attempts to load credentials from environment variables, then from an ini file (.aws/credentials file first, followed by .aws/config file), then from an instance profile (EcsCredentials first, followed by Ec2 metadata).

Note

The result of the default provider is automatically memoized.

assumeRole provider

Aws\Credentials\CredentialProvider::assumeRole is a credential provider that creates credentials using assume role parameters and StsClient information.

To avoid unnecessarily fetching STS credentials on every API operation, you can use
memoize function that handles automatically refreshing the credentials when they expire.

See details with following example code.

use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
use Aws\Sts\StsClient;

// Passing Aws\Credentials\AssumeRoleCredentialProvider options directly
$provider = CredentialProvider::assumeRole([
    'client' => new StsClient(['region' => 'us-west-2', 'version' => 'latest']),
    'assume_role_params' => [
        'RoleArn' => 'arn:aws:iam::012345678910:role/role_name',
        'RoleSessionName' => 'test_session',
    ]
]);

// To avoid unnecessarily fetching STS credentials on every API operation,
// memoize function will handle automatically refreshing the credentials when they expire
$provider = CredentialProvider::memoize($provider);

$client = new S3Client([
    'region'      => 'us-west-2',
    'version'     => 'latest',
    'credentials' => $provider
]);

Creating a custom provider

Credential providers are simply functions that when invoked return a promise (GuzzleHttp\Promise\PromiseInterface) that is fulfilled with an Aws\Credentials\CredentialsInterface object or rejected with an Aws\Exception\CredentialsException.

A best practice for creating providers is to create a function that is invoked to create the actual credential provider. As an example, here's the source of the env provider (slightly modified for example purposes). Notice that it is a function that returns the actual provider function. This allows you to easily compose credential providers and pass them around as values.

use GuzzleHttp\Promise;
use GuzzleHttp\Promise\RejectedPromise;

// This function CREATES a credential provider.
public static function env()
{
    // This function IS the credential provider.
    return function () {
        // Use credentials from environment variables, if available
        $key = getenv(self::ENV_KEY);
        $secret = getenv(self::ENV_SECRET);
        if ($key && $secret) {
            return Promise\promise_for(
                new Credentials($key, $secret, getenv(self::ENV_SESSION))
            );
        }

        $msg = 'Could not find environment variable '
            . 'credentials in ' . self::ENV_KEY . '/' . self::ENV_SECRET;
        return new RejectedPromise(new CredentialsException($msg));
    };
}

Memoizing Credentials

It is sometimes necessary to create a credential provider that remembers the previous return value. This can be useful for performance when loading credentials is an expensive operation or when using the Aws\Sdk class to share a credential provider across multiple clients. You can add memoization to a credential provider by wrapping the credential provider function in a memoize function:

use Aws\Credentials\CredentialProvider;

$provider = CredentialProvider::instanceProfile();
// Wrap the actual provider in a memoize function.
$provider = CredentialProvider::memoize($provider);

// Pass the provider into the Sdk class and share the provider
// across multiple clients. Each time a new client is constructed,
// it will use the previously returned credentials as long as
// they have not yet expired.
$sdk = new Aws\Sdk(['credentials' => $provider]);

$s3 = $sdk->getS3(['region' => 'us-west-2', 'version' => 'latest']);
$ec2 = $sdk->getEc2(['region' => 'us-west-2', 'version' => 'latest']);

assert($s3->getCredentials() === $ec2->getCredentials());

When the memoized credentials become expired, the memoize wrapper will invoke the wrapped provider in an attempt to refresh the credentials.

Chaining providers

Credential providers can be chained using the Aws\Credentials\CredentialProvider::chain() function. This function accepts a variadic number of arguments, each of which are credential provider functions. This function then returns a new function that is the composition of the provided functions such that they are invoked one after the other until one of the providers returns a promise that is fulfilled successfully.

The defaultProvider uses this composition in order to check multiple providers before failing. The source of the defaultProvider demonstrates the use of the chain function.

// This function returns a provider.
public static function defaultProvider(array $config = [])
{
    // This function is the provider, which is actually the composition
    // of multiple providers. Notice that we are memoizing the result by
    // default as well.
    return self::memoize(
        self::chain(
            self::env(),
            self::ini(),
            self::instanceProfile($config)
        )
    );
}

Using temporary credentials from AWS STS

AWS Security Token Service (AWS STS) enables you to request limited-privilege, temporary credentials for AWS IAM users or for users that you authenticate via identity federation. One common use case for using temporary credentials is to grant mobile or client-side applications access to AWS resources by authenticating users through third-party identity providers (read more about Web Identity Federation).

Note

Temporary credentials generated by AWS STS are not supported by every service. Please check if the service you are using supports temporary credentials by reading AWS Services that Support AWS STS.

Getting temporary credentials

AWS STS has several operations that return temporary credentials, but the GetSessionToken operation is the simplest for demonstration purposes. Assuming you have an instance of Aws\Sts\StsClient stored in the $stsClient variable, this is how you call it:

$result = $stsClient->getSessionToken();

The result for GetSessionToken and the other AWS STS operations always contains a 'Credentials' value. If you print the result (e.g., print_r($result)), it looks like the following:

Array
(
    ...
    [Credentials] => Array
    (
        [SessionToken] => '<base64 encoded session token value>'
        [SecretAccessKey] => '<temporary secret access key value>'
        [Expiration] => 2013-11-01T01:57:52Z
        [AccessKeyId] => '<temporary access key value>'
    )
    ...
)

Providing temporary credentials to the SDK

You can use temporary credentials with another AWS client by instantiating the client and passing in the values received from AWS STS directly.

use Aws\S3\S3Client;

$result = $stsClient->getSessionToken();

$s3Client = new S3Client([
    'version'     => '2006-03-01',
    'region'      => 'us-west-2',
    'credentials' => [
        'key'    => $result['Credentials']['AccessKeyId'],
        'secret' => $result['Credentials']['SecretAccessKey'],
        'token'  => $result['Credentials']['SessionToken']
    ]
]);

You can also construct a Aws\Credentials\Credentials object and use that when instantiating the client.

use Aws\Credentials\Credentials;
use Aws\S3\S3Client;

$result = $stsClient->getSessionToken();

$credentials = new Credentials(
    $result['Credentials']['AccessKeyId'],
    $result['Credentials']['SecretAccessKey'],
    $result['Credentials']['SessionToken']
);

$s3Client = new S3Client([
    'version'     => '2006-03-01',
    'region'      => 'us-west-2',
    'credentials' => $credentials
]);

However, the best way to provide temporary credentials is to use the createCredentials() helper method included with the StsClient. This method extracts the data from an AWS STS result and creates the Credentials object for you.

$result = $stsClient->getSessionToken();
$credentials = $stsClient->createCredentials($result);

$s3Client = new S3Client([
    'version'     => '2006-03-01',
    'region'      => 'us-west-2',
    'credentials' => $credentials
]);

For more information about why you might need to use temporary credentials in your application or project, see Scenarios for Granting Temporary Access in the AWS STS documentation.

Creating Anonymous Clients

In some cases, you may want to create a client that is not associated with any credentials. This allows you to make anonymous requests to a service. For example, both S3 Objects and CloudSearch Domains can be configured to allow anonymous access.

To create an anonymous client, you can set the 'credentials' option to false.

$s3Client = new S3Client([
    'version'     => 'latest',
    'region'      => 'us-west-2',
    'credentials' => false
]);

// Makes an anonymous request. The Object would need to be publicly
// readable for this to succeed.
$result = $s3Client->getObject([
    'Bucket' => 'my-bucket',
    'Key'    => 'my-key',
]);