Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS SDK is unable to fetch AWS credentials from AWS IAM Identity Center if the Identity Center access token for an SSO session expiry time is between 5 and 15 minutes from now #4798

Closed
3 tasks done
sjakthol opened this issue Jun 7, 2023 · 6 comments · Fixed by #5124
Assignees
Labels
bug This issue is a bug. needs-review This issue/pr needs review from an internal developer. p2 This is a standard priority issue

Comments

@sjakthol
Copy link
Contributor

sjakthol commented Jun 7, 2023

Checkboxes for prior research

Describe the bug

When using AWS IAM Identity Center based profile with the sso_session option, aws-sdk-js-v3 fails to resolve AWS credentials if the AWS IAM Identity Center SSO session access token expires between 5 and 15 minutes from now.

SDK version number

@aws-sdk/credential-provider-sso@3.347.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v18.16.0

Reproduction Steps

  1. Create file called config with following content (fill in your AWS IAM Identity Center details):
[sso-session mysso]
sso_start_url = https://mysso.awsapps.com/start
sso_region = eu-west-1

[profile profile-1]
sso_session = mysso
sso_account_id = 000000000000
sso_role_name = MyRole
  1. Login to AWS IAM Identity Center: aws sso login --session-name mysso
  2. Create file called index.js with following content:
import {GetCallerIdentityCommand, STSClient} from "@aws-sdk/client-sts"

const client = new STSClient({});
const cmd = new GetCallerIdentityCommand({})
console.log(await client.send(cmd))
  1. Execute following command in a loop for 1 hour (seems to be the expiry time for AWS IAM Identity Center tokens)
env AWS_CONFIG_FILE=./config AWS_REGION=eu-west-1 AWS_PROFILE=profile-1 node index.js

Alternatively, you may manually set the expiresAt field value to ~15 minutes from now in token cache files in ~/.aws/sso/cache/ folder to simulate a token that is about to expire in 15 minutes from now without having to wait full hour to get there.

Observed Behavior

When AWS IAM Identity Center access token expiry time is > 15 minutes from now, AWS SDK is able to fetch AWS credentials from AWS IAM Identity Center with the valid access token.

When AWS IAM Identity Center access token expiry time is < 15 minutes but > 5 minutes from now, AWS SDK rejects the access token as expired and prompts the user to refresh it manually (all AWS API calls fail during this time):

/sdkbug/node_modules/@aws-sdk/credential-provider-sso/dist-cjs/resolveSSOCredentials.js:34
        throw new property_provider_1.CredentialsProviderError(`The SSO session associated with this profile has expired. ${refreshMessage}`, SHOULD_FAIL_CREDENTIAL_CHAIN);
              ^

CredentialsProviderError: The SSO session associated with this profile has expired. To refresh this SSO session run aws sso login with the corresponding profile.
    at resolveSSOCredentials (/sdkbug/node_modules/@aws-sdk/credential-provider-sso/dist-cjs/resolveSSOCredentials.js:34:15)
    at async coalesceProvider (/sdkbug/node_modules/@aws-sdk/property-provider/dist-cjs/memoize.js:14:24)
    at async SignatureV4.credentialProvider (/sdkbug/node_modules/@aws-sdk/property-provider/dist-cjs/memoize.js:33:24)
    at async SignatureV4.signRequest (/sdkbug/node_modules/@aws-sdk/signature-v4/dist-cjs/SignatureV4.js:87:29)
    at async /sdkbug/node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:16:18
    at async /sdkbug/node_modules/@aws-sdk/middleware-retry/dist-cjs/retryMiddleware.js:27:46
    at async /sdkbug/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:7:26
    at async file:///sdkbug/index.js:5:13 {
  tryNextLink: false,
  '$metadata': { attempts: 1, totalRetryDelay: 0 }
}

When AWS IAM Identity Center access token expiry time is < 5 minutes from now, AWS SDK automatically refreshes the token and is able to fetch AWS credentials again using the new token.

Expected Behavior

AWS SDK either accepts the token until it hits the 5 minute mark or refreshes the token automatically already at the 15 minute mark without user intervention.

Possible Solution

Reason for the issue is that the AWS IAM Identity Center token-providers package considers tokens with > 5 minute lifetime as valid and only refreshes them at the 5 minute mark:

if (existingToken.expiration!.getTime() - Date.now() > EXPIRE_WINDOW_MS) {
// Token is valid and not expired.
return existingToken;
}

export const EXPIRE_WINDOW_MS = 5 * 60 * 1000;

However, the user of these tokens, the credential-provider-sso package, rejects AWS IAM Identity Center access token if its lifetime is < 15 minutes:

if (new Date(token.expiresAt).getTime() - Date.now() <= EXPIRE_WINDOW_MS) {
throw new CredentialsProviderError(
`The SSO session associated with this profile has expired. ${refreshMessage}`,
SHOULD_FAIL_CREDENTIAL_CHAIN
);
}

/**
* The time window (15 mins) that SDK will treat the SSO token expires in before the defined expiration date in token.
* This is needed because server side may have invalidated the token before the defined expiration date.
*
* @internal
*/
const EXPIRE_WINDOW_MS = 15 * 60 * 1000;

Hence, if token is set to expire between 5 and 15 minutes from now, token-providers package considers the tokens to be valid while the credential-provider-sso package considers the tokens to be expired.

Additional Information/Context

No response

@sjakthol sjakthol added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jun 7, 2023
@yenfryherrerafeliz yenfryherrerafeliz self-assigned this Jun 7, 2023
sjakthol added a commit to sjakthol/aws-sdk-js-v3 that referenced this issue Jun 8, 2023
… AWS IAM Identity Center tokens

Previously credential-provider-sso would throw an error if an sso-session
based access token was expiring within 15 minutes. However, the sso token
provider would only trigger refresh if the token was expiring within 5
minutes. This lead to situation where the sso token provider would did
not refresh the token before it had 5 minutes of validity left while the
credential-provider-sso rejected the token as expired already at 15
minutes of validity left.

This commit updates credential-provider-sso module to not check the
expiry time of sso-session based AWS IAM Identity Center access tokens.

The sso token provider already has a lot of logic to make sure it only
ever returns valid access tokens. This also aligns the SDK with other
AWS SDKs that do not check the expiry time of refreshable sso-session
tokens but try to refresh the token automatically some time before it
expires or if the token has already expired (botocore, aws-sdk-js v2,
aws-sdk-java v2 and aws-sdk-go-v2 at least work like this).

The credential-provider-sso module will still check the expiry of a cached,
non-refreshable AWS IAM Identity Center token, reject the token and prompt
the user to reauthenticate 15 minutes before the token expires.

Fixes aws#4798.
@sjakthol
Copy link
Contributor Author

sjakthol commented Jun 8, 2023

Proposed a potential fix to this issue at #4812

@spoco2
Copy link

spoco2 commented Jul 24, 2023

Just to confirm that any fix for these issues will also fix the issue where it seems aws-cdk doesn't engage the token refreshing at all? Because aws/aws-cdk#24782 has been said to be tracked by the changes on ☝️. And so I hope that carries over to this too!

@sjakthol
Copy link
Contributor Author

It's not entirely clear if this is the issue that causes the CDK issue you linked to. Currently CDK uses both SDK v2 and v3 internally and I'm not sure which SDK is used for the credential resolution over there.

However, it's very likely that the CDK problem is caused by either this or aws/aws-sdk-js#4441 depending on which SDK version is used there. I guess we'll see that when fix to this and aws/aws-sdk-js#4441 is merged and released, and CDK is updated to take newer version of SDKs into use.

@kellertk
Copy link
Contributor

This was fixed in the Java SDK by simply removing the 15 minute expiration check from the SSO credential provider: aws/aws-sdk-java-v2#4157. Possibly this is safe to do here as well?

Pull created in #5124, but I will discuss further with the team.

@kellertk kellertk added needs-review This issue/pr needs review from an internal developer. p2 This is a standard priority issue and removed needs-triage This issue or PR still needs to be triaged. labels Aug 22, 2023
@kellertk
Copy link
Contributor

@sjakthol created a pull as well that addresses this a little differently, in #4812

@github-actions
Copy link

github-actions bot commented Sep 6, 2023

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue is a bug. needs-review This issue/pr needs review from an internal developer. p2 This is a standard priority issue
Projects
None yet
4 participants