Skip to content

StsAssumeRoleWithWebIdentityCredentialsProvider does not call refreshRequest #5709

Description

@paul-gardiner

Describe the bug

I am using StsAssumeRoleWithWebIdentityCredentialsProvider to assume an AWS role using a token created on Azure AD/Entra. When the AWS token expires, it will get a new token as long as the WebIdentityToken from Entra has not expired. Once the WebIdentityToken expires, the next refresh to get an AWS token results in an ExpiredTokenException.

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

When refreshing the AWS token, I expected refreshRequest to be called, which would update the WebIdentityToken. However, it is not called.

Current Behavior

s.a.a.s.s.m.ExpiredTokenException: Token expired: current date/time 1731098245 must be before the expiration date/time 1731095240 (Service: Sts, Status Code: 400, Request ID: 22679931-6a1d-4db3-abd0-a189de181809)
at s.a.a.c.i.h.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
at s.a.a.c.i.h.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
at s.a.a.c.i.h.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
at s.a.a.c.i.h.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
at s.a.a.c.i.h.p.s.HandleResponseStage.execute(HandleResponseStage.java:50)
at s.a.a.c.i.h.p.s.HandleResponseStage.execute(HandleResponseStage.java:38)
at s.a.a.c.i.h.p.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at s.a.a.c.i.h.p.s.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:74)
at s.a.a.c.i.h.p.s.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:43)
at s.a.a.c.i.h.p.s.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:79)
at s.a.a.c.i.h.p.s.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:41)
at s.a.a.c.i.h.p.s.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:55)
at s.a.a.c.i.h.p.s.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:39)
at s.a.a.c.i.h.p.s.RetryableStage2.executeRequest(RetryableStage2.java:93)
at s.a.a.c.i.h.p.s.RetryableStage2.execute(RetryableStage2.java:56)
at s.a.a.c.i.h.p.s.RetryableStage2.execute(RetryableStage2.java:36)
at s.a.a.c.i.h.p.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at s.a.a.c.i.h.StreamManagingStage.execute(StreamManagingStage.java:53)
at s.a.a.c.i.h.StreamManagingStage.execute(StreamManagingStage.java:35)
at s.a.a.c.i.h.p.s.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:82)
at s.a.a.c.i.h.p.s.Api...

Reproduction Steps

Following is the config class (springboot) that creates the StsAssumeRoleWithWebIdentityCredentialsProvider bean.

@Configuration
@Slf4j
class AwsAssumeRoleConfig {

  @Value("${application.aws-role-session-duration}")
  private int sessionDuration;
  @Value("${application.aws-assumed-role-arn}")
  private String assumedRoleArn;

  @Bean
  StsAssumeRoleWithWebIdentityCredentialsProvider assumeRoleWithWebIdentityCredentialsProvider(
      StsClient stsClient, EntraTokenProvider entraTokenProvider) {
    String sessionName = "cct-" + UUID.randomUUID().toString();
    log.info("Creating StsAssumeRole provider for role: {} with session name {} with duration {}",
        assumedRoleArn, sessionName,
        sessionDuration);

    return StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
        .stsClient(stsClient)
        .asyncCredentialUpdateEnabled(true)
        .refreshRequest(assumeRoleRequest -> {
          log.info("entra token requested for assume role");
          OAuth2AccessToken token = entraTokenProvider.getAccessToken();
          if (log.isDebugEnabled()) {
            log.debug("Token received from entra: {}***********",
                token.getTokenValue().substring(0, 5));
          } else {
            log.info("Token received from entra, length {}", token.getTokenValue().length());
          }
          assumeRoleRequest.webIdentityToken(token.getTokenValue());
          assumeRoleRequest.roleArn(assumedRoleArn);
          assumeRoleRequest.roleSessionName(sessionName);
          assumeRoleRequest.durationSeconds(sessionDuration);
        })
        .build();
  }

  @SuppressWarnings("java:S6242")
  @Bean
  StsClient stsClient() {
    return StsClient.builder()
        .region(Region.CA_CENTRAL_1)

        .build();
  }
}

Possible Solution

No response

Additional Information/Context

Dependencies are:

implementation 'org.springframework.cloud:spring-cloud-stream-binder-kinesis:4.0.4'
implementation 'org.apache.httpcomponents.client5:httpclient5'
implementation 'software.amazon.awssdk:kinesis:2.29.1'
implementation 'software.amazon.awssdk:dynamodb:2.29.1'
implementation 'software.amazon.awssdk:cloudwatch:2.29.1'
implementation 'software.amazon.awssdk:sts:2.29.1'
implementation 'org.springframework.security:spring-security-oauth2-client'
implementation 'com.azure.spring:spring-cloud-azure-stream-binder-eventhubs:5.17.1'
implementation 'com.google.protobuf:protobuf-java:4.28.3'

AWS Java SDK version used

2.29.1

JDK version used

OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)

Operating System and version

Oracle Linux Server 8.10

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.p2This is a standard priority issue

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions