Using AWS IAM with STS as an Identity Provider
03.12.2025
•
Jonathan Merlevede
How EKS tokens are created, and how we can use the same technique to use AWS IAM as an identity provider.
I recently tried to connect to an AWS EKS cluster from Python code in an environment that did not have the aws CLI installed, leaving me without a way to retrieve tokens using aws eks get-token. Looking for a Boto call or AWS API call for EKS tokens yielded no results. I decided to look at how these tokens are generated, and as it turns out, the bearer tokens authenticating you to EKS are pre-signed calls to the AWS STS API — specifically for the GetCallerIdentity endpoint.
Pre-signing calls to GetCallerIdentity lets you use IAM credentials to generate an identity token that works for authenticating to EKS and other contexts. Let’s dive in!

Relationship between EKS and STS
How we usually authenticate to EKS
When using EKS, we typically create a cluster and then run aws eks update-kubeconfig to update our kubeconfig file as described in the AWS documentation.
For example, if we have a cluster named confused-blues-mushroom, we can run:
This updates your ~/.kube/config file with an entry for the cluster, looking like so:
The config file defines your cluster, a user (~credentials), and a context that ties the two together.
A closer look at the user token
The user entry tells us that we can obtain credentials for the cluster by running the following command:
Doing so yields something like this:
Investigating the token further, we see that it consists of a prefix k8s-aws-v1., followed by a URL-safe base64-encoded string. Decoding this string, we get a pre-signed URL for the GetCallerIdentity API call:
Making a straightforward GET request to this URL returns something like this, which could be interpreted as the pre-signed URL being invalid:
Inspection of the pre-signed URL reveals the parameter X-Amz-SignedHeaders=host%3Bx-k8s-aws-id, which tells us that the x-k8s-aws-id header should be included in the request. Assuming that $presigned is the pre-signed URL, the command
returns something like:
If you receive the EKS token, you can decode it and call the embedded pre-signed URL. You then get a lot of information about the identity of the caller; you know its role session ARN arn:aws:sts::<account-id>:assumed-role/<role-name>/<username>, which is tied to the role with ID <role-id> and tagged with userid <userid> (docs).
Understanding all of this is helpful for several reasons. You now know that:
It should be easy to replace the
awsCLI with a more lightweight alternative.You can create your own token generator fairly easily, which can be useful in some environments where the
awsCLI is not available — like Lambda functions.You can use this technique to support authentication using AWS IAM credentials in your own services.
Lightweight AWS alternative
The aws CLI is a rather heavyweight dependency if all you use it for is token creation. You can use a lighter alternative instead, such as aws-iam-authenticator. Their GitHub page does a pretty good job of explaining the above process, too.
To use aws-iam-authenticator instead of aws, install it and adapt the user entry in your kubeconfig file as follows:
Indeed, the output of the aws-iam-authenticator command is exactly the same as the output of the aws eks get-token command.
Generating your own tokens
You can also generate tokens yourself. It helps if you can use a library to handle the heavy lifting — in casu, the AWS Signature v4 (SigV4) signing.
The README documentation of aws-iam-authenticator provides a great example of how to do this using Python (link):
A token generated by this function can be used as a bearer token in calls to the Kubernetes API.
Supporting IAM authentication in your own services
You can use this technique to support IAM authentication in our own services. That’s also the idea behind aws-iam-authenticator, which allows you to add IAM authentication to self-managed Kubernetes clusters.
In fact, aws-iam-authenticator even predates Amazon EKS! EKS adopted the authentication approach introduced by aws-iam-authenticator, standardizing it.
The mechanics are straightforward:
The
x--prefixed header(s) that you add to your call to AWS STS ensure that your pre-signed URL is used only in the context of the service that you are targeting (e.g., a specific EKS cluster). They serve as what would be known as your token’saudclaim in OIDC or your assertion’s audience restriction in SAML.On the protected resource side, validate incoming tokens by calling the pre-signed URL you receive with the appropriate headers. This is not too different from how OAuth with token introspection works.
Several services besides EKS use this method. It is, for example, how HashiCorp Vault’s IAM auth method works:

https://developer.hashicorp.com/vault/docs/auth/aws
Note that STS is not the perfect identity provider for several reasons, including but not limited to:
Generating the token is somewhat complicated; it does not follow a “standard” flow (think the OAuth client credentials flow) and requires SigV4 signing.
STS calls are free, but e.g. throttling might become an issue. The default quota allows 600 requests per second.
Having to call the pre-signed URLs for all incoming requests imposes a load on your protected resource. Self-contained tokens such as JWS-encoded tokens (~JWT) are typically better in this regard.
You will have to validate the incoming pre-signed URL before calling it for security reasons.
Summary
We explored how EKS uses AWS STS to construct bearer tokens for Kubernetes API access by pre-signing calls to GetCallerIdentity. This technique is not limited to EKS — you can use it to add IAM authentication to your own services, just like HashiCorp Vault does. Whether you need to create tokens in environments without the aws CLI or want to build your own IAM-based authentication system, understanding this pattern opens up some interesting possibilities.
Latest
Using AWS IAM with STS as an Identity Provider
How EKS tokens are created, and how we can use the same technique to use AWS IAM as an identity provider.
Slaying the Terraform Monostate Beast
You start out building your data platform. You choose Terraform because you want to do it the right way and put your infra in code.
How to Prevent Crippling Your Infrastructure When AWS US-EAST-1 Fails
Practical lessons on designing for resilience and how to reduce your exposure in case of a major cloud outage.



