How to use an external ID when granting access to your AWS resources to a third party - AWS Identity and Access Management

How to use an external ID when granting access to your AWS resources to a third party

At times, you need to give a third party access to your AWS resources (delegate access). One important aspect of this scenario is the External ID, optional information that you can use in an IAM role trust policy to designate who can assume the role.


AWS does not treat the external ID as a secret. After you create a secret like an access key pair or a password in AWS, you cannot view them again. The external ID for a role can be seen by anyone with permission to view the role.

In a multi-tenant environment where you support multiple customers with different AWS accounts, we recommend using one external ID per AWS account. This ID should be a random string generated by the third party.

To require that the third party provides an external ID when assuming a role, update the role's trust policy with the external ID of your choice.

To provide an external ID when you assume a role, use the AWS CLI or AWS API to assume that role. For more information, see the STS AssumeRole API operation, or the STS assume-role CLI operation.

For example, let's say that you decide to hire a third-party company called Example Corp to monitor your AWS account and help optimize costs. In order to track your daily spending, Example Corp needs to access your AWS resources. Example Corp also monitors many other AWS accounts for other customers.

Do not give Example Corp access to an IAM user and its long-term credentials in your AWS account. Instead, use an IAM role and its temporary security credentials. An IAM role provides a mechanism to allow a third party to access your AWS resources without needing to share long-term credentials (for example, an IAM user's access key).

You can use an IAM role to establish a trusted relationship between your AWS account and the Example Corp account. After this relationship is established, a member of the Example Corp account can call the AWS Security Token Service AssumeRole API to obtain temporary security credentials. The Example Corp members can then use the credentials to access AWS resources in your account.


For more information about the AssumeRole and other AWS API operations that you can call to obtain temporary security credentials, see Requesting temporary security credentials.

Here's a more detailed breakdown of this scenario:

  1. You hire Example Corp, so they create a unique customer identifier for you. They provide you with this unique customer ID and their AWS account number. You need this information to create an IAM role in the next step.


    Example Corp can use any string value they want for the ExternalId, as long as it is unique for each customer. It can be a customer account number or even a random string of characters, as long as no two customers have the same value. It is not intended to be a 'secret'. Example Corp must provide the ExternalId value to each customer. What is crucial is that it must be generated by Example Corp and not their customers.

  2. You sign in to AWS and create an IAM role that gives Example Corp access to your resources. Like any IAM role, the role has two policies, a permission policy and a trust policy. The role's trust policy specifies who can assume the role. In our sample scenario, the policy specifies the AWS account number of Example Corp as the Principal. This allows identities from that account to assume the role. In addition, you add a Condition element to the trust policy. This Condition tests the ExternalId context key to ensure that it matches the unique customer ID from Example Corp. For example:

    "Principal": {"AWS": "Example Corp's AWS Account ID"}, "Condition": {"StringEquals": {"sts:ExternalId": "Unique ID Assigned by Example Corp"}}
  3. The permission policy for the role specifies what the role allows someone to do. For example, you could specify that the role allows someone to manage only your Amazon EC2 and Amazon RDS resources but not your IAM users or groups. In our sample scenario, you use the permission policy to give Example Corp read-only access to all of the resources in your account.

  4. After you create the role, you provide the Amazon Resource Name (ARN) of the role to Example Corp.

  5. When Example Corp needs to access your AWS resources, someone from the company calls the AWS sts:AssumeRole API. The call includes the ARN of the role to assume and the ExternalId parameter that corresponds to their customer ID.

If the request comes from someone using Example Corp's AWS account, and if the role ARN and the external ID are correct, the request succeeds. It then provides temporary security credentials that Example Corp can use to access the AWS resources that your role allows.

In other words, when a role policy includes an external ID, anyone who wants to assume the role must be a principal in the role and must include the correct external ID.

Why use an external ID?

In abstract terms, the external ID allows the user that is assuming the role to assert the circumstances in which they are operating. It also provides a way for the account owner to permit the role to be assumed only under specific circumstances. The primary function of the external ID is to address and prevent the "confused deputy" problem.

The confused deputy problem

To continue the previous example, Example Corp requires access to certain resources in your AWS account. But in addition to you, Example Corp has other customers and needs a way to access each customer's AWS resources. Instead of asking its customers for their AWS account access keys, which are secrets that should never be shared, Example Corp requests a role ARN from each customer. But another Example Corp customer might be able to guess or obtain your role ARN. That customer could then use your role ARN to gain access to your AWS resources by way of Example Corp. This form of permission escalation is known as the confused deputy problem.

The following diagram illustrates the confused deputy problem.

          The description of a confused deputy problem.

This scenario assumes the following:

  • AWS1 is your AWS account.

  • AWS1:ExampleRole is a role in your account. This role's trust policy trusts Example Corp by specifying Example Corp's AWS account as the one that can assume the role.

Here's what happens:

  1. When you start using Example Corp's service, you provide the ARN of AWS1:ExampleRole to Example Corp.

  2. Example Corp uses that role ARN to obtain temporary security credentials to access resources in your AWS account. In this way, you are trusting Example Corp as a "deputy" that can act on your behalf.

  3. Another AWS customer also starts using Example Corp's service, and this customer also provides the ARN of AWS1:ExampleRole for Example Corp to use. Presumably the other customer learned or guessed the AWS1:ExampleRole, which isn't a secret.

  4. When the other customer asks Example Corp to access AWS resources in (what it claims to be) its account, Example Corp uses AWS1:ExampleRole to access resources in your account.

This is how the other customer could gain unauthorized access to your resources. Because this other customer was able to trick Example Corp into unwittingly acting on your resources, Example Corp is now a "confused deputy."

How does an external ID prevent the confused deputy problem?

You address the confused deputy problem by including the ExternalId condition check in the role's trust policy. The "deputy" company inserts a unique external ID value for each customer into the request for AWS credentials. The external ID is a customer ID value that must be unique among Example Corp's customers and is out of the control of Example Corp's customers. This is why you get it from Example Corp and you don't come up with it on your own. This helps prevent one customer from successfully impersonating another customer. Example Corp always inserts the customer's assigned external ID, so you should never see a request coming from Example Corp with any external ID except your own.

In our scenario, imagine Example Corp's unique identifier for you is "12345," and its identifier for the other customer is "67890." These identifiers are simplified for this scenario. Generally, these identifiers are GUIDs. Assuming that these identifiers are unique among Example Corp's customers, they are sensible values to use for the external ID.

Example Corp gives the external ID value of "12345" to you. You must then add a Condition element to the role's trust policy that requires the sts:ExternalId value to be 12345, like this:

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Principal": {"AWS": "Example Corp's AWS Account ID"}, "Condition": {"StringEquals": {"sts:ExternalId": "12345"}} } }

The Condition element in this policy allows Example Corp to assume the role only when the AssumeRole API call includes the external ID value of "12345". Example Corp makes sure that whenever it assumes a role on behalf of a customer, it always includes that customer's external ID value in the AssumeRole call. Even if another customer supplies Example Corp with your ARN, it cannot control the external ID that Example Corp includes in its request to AWS. This helps prevent an unauthorized customer from gaining access to your resources.

The following diagram illustrates this.

          How to mitigate a confused deputy problem.
  1. As before, when you start using Example Corp's service, you provide the ARN of AWS1:ExampleRole to Example Corp.

  2. When Example Corp uses that role ARN to assume the role AWS1:ExampleRole, Example Corp includes your external ID ("12345") in the AssumeRole API call. The external ID matches the role's trust policy, so the AssumeRole API call succeeds and Example Corp obtains temporary security credentials to access resources in your AWS account.

  3. Another AWS customer also starts using Example Corp's service, and as before, this customer also provides the ARN of AWS1:ExampleRole for Example Corp to use.

  4. But this time, when Example Corp attempts to assume the role AWS1:ExampleRole, it provides the external ID associated with the other customer ("67890"). The other customer has no way to change this. Example Corp does this because the request to use the role came from the other customer, so "67890" indicates the circumstance in which Example Corp is acting. Because you added a condition with your own external ID ("12345") to the trust policy of AWS1:ExampleRole, the AssumeRole API call fails. The other customer is prevented from gaining unauthorized access to resources in your account (indicated by the red "X" in the diagram).

The external ID helps prevent any other customer from tricking Example Corp into unwittingly accessing your resources–it mitigates the confused deputy problem.

When should I use an external ID?

Use an external ID in the following situations:

  • You are an AWS account owner and you have configured a role for a third party that accesses other AWS accounts in addition to yours. You should ask the third party for an external ID that it includes when it assumes your role. Then you check for that external ID in your role's trust policy. Doing so ensures that the external party can assume your role only when it is acting on your behalf.

  • You are in the position of assuming roles on behalf of different customers like Example Corp in our previous scenario. You should assign a unique external ID to each customer and instruct them to add the external ID to their role's trust policy. You must then ensure that you always include the correct external ID in your requests to assume roles.

    You probably already have a unique identifier for each of your customers, and this unique ID is sufficient for use as an external ID. The external ID is not a special value that you need to create explicitly, or track separately, just for this purpose.

    You should always specify the external ID in your AssumeRole API calls. In addition when a customer gives you a role ARN, test whether you can assume the role both with and without the correct external ID. If you can assume the role without the correct external ID, don't store the customer's role ARN in your system. Wait until your customer has updated the role trust policy to require the correct external ID. In this way you help your customers to do the right thing, which helps to keep both of you protected against the confused deputy problem.