aws / aws-sdk-java-v2

The official AWS SDK for Java - Version 2
Apache License 2.0
2.16k stars 833 forks source link

SSO OIDC access token may expire while application is running #3777

Open GFriedrich opened 1 year ago

GFriedrich commented 1 year ago

Describe the bug

When using the SSO session introduced in last November, the access token of the SSO session is used. If this access token is expiring while the application is running, all requests to AWS will fail.

Expected Behavior

I would expect that the access token of SSO sessions are refresh throughtout the applications lifetime, so AWS requests don't fail.

Current Behavior

The access token of the SSO session is only refreshed when the client gets constructed. If the access token expires throughout the applications lifetime, the AWS calls will fail.

Reproduction Steps

  1. Make your local AWS config use the SSO sessions.
  2. Start an application e.g. using an S3 client via:
    S3Client.builder().credentialsProvider(ProfileCredentialsProvider.create(SOME_SSO_PROFILE_NAME))
  3. Keep the application running until the access token of your current session expires.
  4. Try to call the S3 client.

Possible Solution

When checking the code I found this part: https://github.com/aws/aws-sdk-java-v2/blob/b74ce8e270b25c51a1ae0da1013488f9150dd5ad/services/sso/src/main/java/software/amazon/awssdk/services/sso/auth/SsoProfileCredentialsProviderFactory.java#L107-L111

You can see that resolveToken() is called during construction time. This method refreshes the access token if required. But the following supplier will simply make use of the given access token.

I'm wondering whether it would be enough to simply call the resolveToken() inside of the supplier for the GetRoleCredentialsRequest, so that the access token gets refreshed beforehand. 🤔

Additional Information/Context

No response

AWS Java SDK version used

2.20.7

JDK version used

17.0.6

Operating System and version

Windows 10 22H2

debora-ito commented 1 year ago

Hi @GFriedrich thank you for reaching out.

Which type of credential configuration you are using, the SSO token provider or the legacy? For more info: https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html

Legacy type of credentials can't be refreshed automatically, you need to run aws sso login --profile PROFILE_NAME to refresh the credentials.

Have you tried using the SsoCredentialsProvider? https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sso/auth/SsoCredentialsProvider.html

GFriedrich commented 1 year ago

Hi @debora-ito and thanks for getting back at me.

As mentioned in the first post I'm using an SSO session within the AWS config - or in other words: Yes, I'm using the SSO token provider and not the legacy one.

Also as mentioned above I'm using ProfileCredentialsProvider.create(SOME_SSO_PROFILE_NAME) to create the credentials provider. If you follow the code path, you will see that this in turn creates an SsoProfileCredentialsProvider which in turn makes use of the SsoCredentialsProvider - so again: Yes, I'm using this, but it doesn't help as the SsoCredentialsProvider doesn't refresh the existing access token and simply fails after the access token expires.

Only the SsoProfileCredentialsProvider refreshes the access token but only during creation time which is counter-intuitive and I would expect that the SDK handles the refresh transparently even during runtime of the application.

amank22 commented 1 year ago

This is what I can understand the issue is:

https://github.com/aws/aws-sdk-java-v2/blob/8ce3173aa0327ef54a13147a6d896e86b1b9b95f/services/ssooidc/src/main/java/software/amazon/awssdk/services/ssooidc/SsoOidcTokenProvider.java#L95-L99

SsoOidcTokenProvider -> resolveToken() throws exception is token is already expired. refreshIfStaleAndFetch is giving cached token.

https://github.com/aws/aws-sdk-java-v2/blob/8ce3173aa0327ef54a13147a6d896e86b1b9b95f/services/sso/src/main/java/software/amazon/awssdk/services/sso/auth/SsoProfileCredentialsProviderFactory.java#L107

SsoProfileCredentialsProvider refreshes token.

It calls resolveToken() before refreshing token, but because SsoOidcTokenProvider already throws an exception, it fails to refresh the token in case token is already expired.

RafaelCavazza commented 5 months ago

Hi!

Any update on this issue? We are having the same problem