Issue Temporary Credentials for Roles Corresponding to User Pool Groups with Token/Rule-Based Mapping in Cognito Identity Pool

awsauth

Cognito Identity Pool can issue temporary AWS credentials to users authenticated by IdPs such as User Pool.

CDKでCognito UserPoolとClientを作成しトリガーやFederationを設定する - sambaiz-net

const identityPool = new cognito.CfnIdentityPool(this, 'IdentityPool', {
  identityPoolName: 'test-identity-pool',
  allowUnauthenticatedIdentities: false,
  cognitoIdentityProviders: [{
    clientId: userPoolClient.userPoolClientId,
    providerName: userPool.userPoolProviderName,
  }],
});

The IAM Role for issued credentials can be configured either Token-based using the cognito:preferred_role claim from the group with minimum precedence or cognito:roles claim + CustomRoleArn, or Rule-based using any claim.

const defaultRole = new iam.Role(this, 'DefaultRole', {
  roleName: `default-role`,
  assumedBy: new iam.FederatedPrincipal(
    'cognito-identity.amazonaws.com',
    {
      'StringEquals': {
        'cognito-identity.amazonaws.com:aud': identityPool.ref,
      },
      'ForAnyValue:StringLike': {
        'cognito-identity.amazonaws.com:amr': 'authenticated',
      },
    },
    'sts:AssumeRoleWithWebIdentity'
  ),
});


new cognito.CfnUserPoolGroup(this, 'AdminGroup', {
  userPoolId: userPool.userPoolId,
  groupName: 'admin-users',
  description: 'Admin users',
  roleArn: defaultRole.roleArn, // cognito:roles, cognito:preferred_role (Token based role mapping)
  precedence: 0,
});

new cognito.CfnIdentityPoolRoleAttachment(this, 'RoleAttachment', {
  identityPoolId: identityPool.ref,
  roles: {
    authenticated: defaultRole.roleArn,
  },
  roleMappings: {
    'cognito': {
      identityProvider: `${userPool.userPoolProviderName}:${userPoolClient.userPoolClientId}`,
      type: 'Rules', // or Token
      ambiguousRoleResolution: 'AuthenticatedRole',
      rulesConfiguration: {
        rules: [
          {
            claim: 'cognito:groups',
            matchType: 'Contains',
            value: 'admin-users',
            roleArn: adminRole.roleArn,
          },
          {
            claim: 'cognito:groups',
            matchType: 'Contains',
            value: 'normal-users',
            roleArn: normalRole.roleArn,
          },
        ],
      },
    },
  },
});

You can obtain credentials as follows.

import { CognitoIdentityClient, GetIdCommand, GetCredentialsForIdentityCommand } from '@aws-sdk/client-cognito-identity';

const client = new CognitoIdentityClient({ region: 'ap-northeast-1' });
const providerName = `cognito-idp.ap-northeast-1.amazonaws.com/${userPoolId}`;

const getIdResponse = await client.send(new GetIdCommand({
  IdentityPoolId: identityPoolId,
  Logins: { [providerName]: idToken },
}));

const credentialsResponse = await client.send(new GetCredentialsForIdentityCommand({
  IdentityId: getIdResponse.IdentityId,
  Logins: { [providerName]: idToken },
}));

const credentials = {
  accessKeyId: credentialsResponse.Credentials.AccessKeyId,
  secretAccessKey: credentialsResponse.Credentials.SecretKey,
  sessionToken: credentialsResponse.Credentials.SessionToken,
};