Skip to content

aws-cognito-identitypool-alpha: Can't add rules for the default authenticated role #27411

@kristianhalte

Description

@kristianhalte

Describe the bug

I am trying to configure an IdentityPool with google as an authenticationProviders and add some custom rules through roleMappings.

It's neither possible directly through the initiation of the IdentityPool, nor later through the addRoleMappings() method.

Expected Behavior

To be able to add custom rules to the default roles during initiation of the IdentityPool, or add them later with the addRoleMappings() method

Current Behavior

Getting errors that the DefaultRoleAttachment failed to update, so can't create a new one

The following resource(s) failed to create: [identitypoolRoleMappingAttachmentXXXXXXXXX]. The following resource(s) failed to update: [identitypoolDefaultRoleAttachmentYYYYYYYY]. 

Reproduction Steps

Since this isn't possible

new IdentityPool(stack, 'identity-pool', {
  allowUnauthenticatedIdentities: false,
  authenticationProviders: {
    google: {
      clientId: '12345678012.apps.googleusercontent.com',
    },
  },
  roleMappings: [
    {
      providerUrl: IdentityPoolProviderUrl.GOOGLE,
      rules: [
        {
          claim: 'sub',
          claimValue: '12345678012',
          mappedRole: 'default-auth-role-reference', // 👈 it would be nice if we could reference the default roles directly during initiation of the identitypool
         },
      ],
    },
  ],
})

I instead tried this

const identityPool = new IdentityPool(stack, 'identity-pool', {
  allowUnauthenticatedIdentities: false,
  authenticationProviders: {
    google: {
      clientId: '12345678012.apps.googleusercontent.com',
    },
  },
})

identityPool.addRoleMappings({
  providerUrl: IdentityPoolProviderUrl.GOOGLE,
  rules: [
    {
      claim: 'sub',
      claimValue: '12345678012',
      mappedRole: identityPool.authenticatedRole,
    },
  ],
})

Possible Solution

I don't have a technical solution to solve this, but I managed to get it working in a not so pretty way

// 1. create a new admin role
const adminRole = new Role(stack, 'admin-role', {
  assumedBy: new WebIdentityPrincipal('cognito-identity.amazonaws.com', {
    StringEquals: {
      'cognito-identity.amazonaws.com:aud': 'something-silly', // 👈 we unfortunately don't know the poolId yet
    },
    'ForAnyValue:StringLike': {
      'cognito-identity.amazonaws.com:amr': 'authenticated',
    },
  }),
})

// 2. create the identity pool
const identityPool = new IdentityPool(stack, 'identity-pool', {
  allowUnauthenticatedIdentities: false,
  authenticationProviders: {
    google: {
      clientId: '12345678012.apps.googleusercontent.com',
    },
  },
  roleMappings: [
    {
      providerUrl: IdentityPoolProviderUrl.GOOGLE,
      rules: [
        {
          claim: 'sub',
          claimValue: '12345678012',
          mappedRole: adminRole, // 👈 it is possible to reference the adminRole during initiation of the identityPool
        },
      ],
    },
  ],
})

// 3. create a new policy statement to the admin role, to include the poolId
const adminRolePolicyStatement = new PolicyStatement({
  principals: [new WebIdentityPrincipal('cognito-identity.amazonaws.com')],
  actions: ['sts:AssumeRoleWithWebIdentity'],
  conditions: {
    StringEquals: {
      'cognito-identity.amazonaws.com:aud': identityPool.identityPoolId, // 👈 only now can we reference the poolId
    },
    'ForAnyValue:StringLike': {
      'cognito-identity.amazonaws.com:amr': 'authenticated',
    },
  },
})

// 4. attach the policy statement to the admin role
adminRole.assumeRolePolicy?.addStatements(adminRolePolicyStatement)

This approach works, but it's not very intuitive and it does have two undesirable outcomes

  1. we get an extra role (adminRole) when we could have just used the default AuthenticatedRole
  2. we get an unnecessary policy statement on the admin role
{
  "Version": "2012-10-17",
  "Statement": [
    // this statement is not needed
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "something-silly"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "authenticated"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "[AWS:REGION]:[POOLID]"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "authenticated"
        }
      }
    }
  ]
}

Additional Information/Context

No response

CDK CLI Version

2.99.1

Framework Version

No response

Node.js Version

v20.8.0

OS

MacOS Ventura 13.5.2

Language

Typescript

Language Version

5.2.2

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions