Skip to content

Commit dbe110d

Browse files
committed
fix(auth): SSO source profile authentication fails with invalid token error
Problem: Profiles sourced from SSO profiles fail to authenticate with 'The security token included in the request is invalid' error. This is a regression introduced in v3.47.0 by commit 6f6a8c2. Solution: - Add recursive credential resolution for source profiles in makeSharedIniFileCredentialsProvider() - Check if source profile has static credentials; if not, recursively resolve them - Use resolved credentials for STS client instead of undefined values - Add test case for SSO source profile authentication Fixes #6782
1 parent 7b161da commit dbe110d

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

packages/core/src/auth/providers/sharedCredentialsProvider.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,23 @@ export class SharedCredentialsProvider implements CredentialsProvider {
408408
}
409409
// Use source profile to assume IAM role based on role ARN provided.
410410
const sourceProfile = iniData[profile.source_profile!]
411-
const stsClient = new DefaultStsClient(this.getDefaultRegion() ?? 'us-east-1', {
412-
accessKeyId: sourceProfile.aws_access_key_id!,
413-
secretAccessKey: sourceProfile.aws_secret_access_key!,
414-
})
411+
412+
// Check if source profile has static credentials
413+
let sourceCredentials: AWS.Credentials
414+
if (sourceProfile.aws_access_key_id && sourceProfile.aws_secret_access_key) {
415+
// Source profile has static credentials
416+
sourceCredentials = {
417+
accessKeyId: sourceProfile.aws_access_key_id,
418+
secretAccessKey: sourceProfile.aws_secret_access_key,
419+
sessionToken: sourceProfile.aws_session_token,
420+
}
421+
} else {
422+
// Source profile needs to be resolved (e.g., SSO profile)
423+
const sourceProvider = new SharedCredentialsProvider(profile.source_profile!, this.sections)
424+
sourceCredentials = await sourceProvider.getCredentials()
425+
}
426+
427+
const stsClient = new DefaultStsClient(this.getDefaultRegion() ?? 'us-east-1', sourceCredentials)
415428
// Prompt for MFA Token if needed.
416429
const assumeRoleReq = {
417430
RoleArn: profile.role_arn,

packages/core/src/test/credentials/provider/sharedCredentialsProvider.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,47 @@ describe('SharedCredentialsProvider', async function () {
516516
assert.strictEqual(creds.sessionToken, 'token')
517517
})
518518

519+
it('assumes role with SSO source profile', async function () {
520+
const sections = await createTestSections(`
521+
[profile default]
522+
sso_account_id = 012345678910
523+
sso_role_name = admin
524+
sso_region = us-east-1
525+
sso_registration_scopes = sso:account:access
526+
sso_start_url = https://d-xxxxxxxxx.awsapps.com/start
527+
region = us-east-1
528+
output = json
529+
530+
[profile test]
531+
source_profile = default
532+
role_arn = testarn
533+
region = us-east-1
534+
`)
535+
536+
// Mock SSO credentials for the source profile
537+
const ssoClient = stub(SsoClient, { region: 'us-east-1' })
538+
ssoClient.getRoleCredentials.callsFake(async (request) => {
539+
assert.strictEqual(request.accountId, '012345678910')
540+
assert.strictEqual(request.roleName, 'admin')
541+
542+
return {
543+
accessKeyId: 'sso-access-key',
544+
secretAccessKey: 'sso-secret-key',
545+
sessionToken: 'sso-session-token',
546+
expiration: new Date(Date.now() + oneDay),
547+
}
548+
})
549+
sandbox.stub(SsoClient, 'create').returns(ssoClient)
550+
sandbox.stub(SsoAccessTokenProvider.prototype, 'getToken').resolves()
551+
sandbox.stub(SsoAccessTokenProvider.prototype, 'createToken').resolves()
552+
553+
const sut = new SharedCredentialsProvider('test', sections)
554+
const creds = await sut.getCredentials()
555+
assert.strictEqual(creds.accessKeyId, 'id')
556+
assert.strictEqual(creds.secretAccessKey, 'secret')
557+
assert.strictEqual(creds.sessionToken, 'token')
558+
})
559+
519560
it('does not assume role when no roleArn is present', async function () {
520561
const sut = new SharedCredentialsProvider('default', await createTestSections(defaultSection))
521562
const creds = await sut.getCredentials()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Profiles sourced from SSO profiles fail to authenticate with 'invalid security token' error"
4+
}

0 commit comments

Comments
 (0)