You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AWS CDK创建Cognito栈时遭遇InvalidParameterException错误求助

Cognito身份池创建报错:Invalid Cognito Identity Provider

问题描述

作为AWS CloudFormation与CDK新手,在创建测试栈时持续收到以下错误:

Invalid Cognito Identity Provider (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: InvalidParameterException; Request ID: 7db28b4b-373b-4808-9c8d-1d197b0be542; Proxy: null)

原代码如下:

const cdk = require('aws-cdk-lib');
const ec2 = require('aws-cdk-lib/aws-ec2');
const apigateway = require('aws-cdk-lib/aws-apigateway');
const cognito = require('aws-cdk-lib/aws-cognito');
const iam = require('aws-cdk-lib/aws-iam');
const { Stack } = require('aws-cdk-lib');

class MyCdkStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // Create a VPC for the EC2 instance
    const vpc = new ec2.Vpc(this, 'MyVPC', {
      maxAzs: 2 // Use 2 availability zones
    });

    const sg = new ec2.SecurityGroup(this, 'MySSHSecurityGroup', {
      vpc,
      description: 'Allow Outbound SSH access',
      securityGroupName: 'My SSH Security Group',
      allowAllOutbound: true // Allow all outbound traffic
    });

    // Allow SSH access from a specific IP range
    sg.addIngressRule(ec2.Peer.ipv4('anipaddress/32'), ec2.Port.tcp(22), 'Allow inbound SSH access from here');
    sg.addIngressRule(ec2.Peer.ipv4('anipaddress/32'), ec2.Port.tcp(22), 'Allow inbound SSH access from here 2');

    /////////////////////

    // Create a Cognito user pool
    const userPool = new cognito.UserPool(this, 'MyUserPool', {
      userPoolName: 'My User Pool',
      selfSignUpEnabled: true,
      autoVerify: { email: true },
      signInAliases: { email: true },
      passwordPolicy: {
        minLength: 8,
        requireDigits: true,
        requireLowercase: true,
        requireUppercase: true,
        requireSymbols: true
      }
    });

    const userPoolClient = new cognito.CfnUserPoolClient(this, "MyUserPoolClient", {
      userPoolId: userPool.ref,
      explicitAuthFlows: ["ADMIN_NO_SRP_AUTH"],
      generateSecret: false,
      readAttributes: [
        "preferred_username",
        "website",
        "email",
        "name",
        "zoneinfo",
        "phone_number",
        "phone_number_verified",
        "email_verified",
      ],
      writeAttributes: ["name", "zoneinfo", "phone_number"],
    });

    // Create a Cognito identity pool
    const identityPool = new cognito.CfnIdentityPool(this, 'MyIdentityPool', {
      identityPoolName: 'My Identity Pool',
      allowUnauthenticatedIdentities: false,
      cognitoIdentityProviders: [{
        clientId: userPoolClient.ref,
        providerName: userPool.userPoolProviderName,
      }]
    });

    // Create an API Gateway REST API
    const restApi = new apigateway.RestApi(this, 'MyRestApi', {
      restApiName: 'My Rest API',
      deployOptions: {
        stageName: 'prod'
      }
    });

    const sg2 = new ec2.SecurityGroup(this, 'MyAPIGatewaySecurityGroup', {
      vpc,
      description: 'Allow port 80 traffic from the API Gateway',
      securityGroupName: 'My API Gateway Security Group',
      allowAllOutbound: true // Allow all outbound traffic
    });

    // Allow port 80 traffic from the API Gateway
    sg2.addIngressRule(
      ec2.Peer.ipv4(`${restApi.restApiId}.execute-api.${cdk.Stack.of(this).region}.amazonaws.com/32`),
      ec2.Port.tcp(80),
      'Allow port 80 traffic from the API Gateway'
    );

    const keyName = 'my-key-pair';

    // Create an EC2 key pair for SSH access
    const key = new ec2.CfnKeyPair(this, 'MyKeyPair', {
      keyName,
    });

    // Associate the key pair with the EC2 instance
    const instance = new ec2.Instance(this, 'MyEC2Instance', {
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: new ec2.AmazonLinuxImage(),
      vpc,
      securityGroup: sg2,
      key,
      userData: ec2.UserData.custom(`
      #!/bin/bash
      echo "Hello, world!" > /var/www/html/index.html
      `)
    });

    // Create a Cognito authorizer
    const authorizer = new apigateway.CfnAuthorizer(this, 'MyCognitoAuthorizer', {
      name: 'My-Cognito-Authorizer',
      identitySource: 'method.request.header.Authorization',
      restApiId: restApi.restApiId,
      type: apigateway.AuthorizationType.COGNITO,
      providerArns: [userPool.userPoolArn]
    });

    // Create a resource and method for the API Gateway and Add the Cognito authorizer to the method
    const resource = restApi.root.addResource('my-resource');
    const method = resource.addMethod('GET', new apigateway.HttpIntegration(`http://${instance.instancePublicIp}`),
      {
        authorizationType: apigateway.AuthorizationType.COGNITO, authorizer: authorizer
      });

    // Create an IAM role for authenticated users
    const authenticatedRole = new iam.Role(this, 'MyAuthenticatedRole', {
      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')
    });

    // Create an IAM role for unauthenticated users
    const unauthenticatedRole = new iam.Role(this, 'MyUnauthenticatedRole', {
      assumedBy: new iam.FederatedPrincipal('cognito-identity.amazonaws.com', {
        StringEquals: { 'cognito-identity.amazonaws.com:aud': identityPool.ref },
        'ForAnyValue:StringLike': { 'cognito-identity.amazonaws.com:amr': 'unauthenticated' }
      }, 'sts:AssumeRoleWithWebIdentity')
    });

    // Grant permissions to the authenticated role
    authenticatedRole.addToPolicy(new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: [
        'execute-api:Invoke'
      ],
      resources: [
        method.methodArn
      ]
    }));

    // Grant permissions to the unauthenticated role
    unauthenticatedRole.addToPolicy(new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: [
        'cognito-identity:GetId',
        'cognito-identity:GetOpenIdToken'
      ],
      resources: [
        `arn:aws:cognito-identity:${this.region}:${this.account}:identitypool/${identityPool.ref}`
      ]
    }));

    // Set the roles for authenticated and unauthenticated users
    new cognito.CfnIdentityPoolRoleAttachment(this, 'MyIdentityPoolRoles', {
      identityPoolId: identityPool.ref,
      roles: {
        authenticated: authenticatedRole.roleArn,
        unauthenticated: unauthenticatedRole.roleArn
      }
    });
  }
}

module.exports = { MyCdkStack }

// const app = new cdk.App();
// new MyStack(app, 'MyStack');

问题原因

报错源于Cognito身份池配置的用户池提供者参数错误:

  • 使用底层CfnIdentityPool构造时,cognitoIdentityProviders中的providerName需要传入用户池的完整ARN,而非userPoolProviderName(该属性是简化的提供者名称,不符合身份池的参数要求)。
  • 更推荐使用CDK的L2构造IdentityPool,它会自动处理用户池和客户端的关联,避免手动配置错误。

解决方案

修正方案1:使用L2构造IdentityPool(推荐)

替换原有的CfnIdentityPool代码,改用更简洁的L2构造,自动关联用户池和客户端:

// 替换原有的CfnUserPoolClient和CfnIdentityPool创建代码
const userPoolClient = new cognito.UserPoolClient(this, "MyUserPoolClient", {
  userPool: userPool,
  authFlows: {
    adminUserPassword: true // 对应原ADMIN_NO_SRP_AUTH
  },
  generateSecret: false,
  readAttributes: new cognito.ClientAttributes()
    .withStandardAttributes({
      preferredUsername: true,
      website: true,
      email: true,
      name: true,
      zoneinfo: true,
      phoneNumber: true,
      phoneNumberVerified: true,
      emailVerified: true
    }),
  writeAttributes: new cognito.ClientAttributes()
    .withStandardAttributes({
      name: true,
      zoneinfo: true,
      phoneNumber: true
    })
});

// 使用L2 IdentityPool构造
const identityPool = new cognito.IdentityPool(this, 'MyIdentityPool', {
  identityPoolName: 'My Identity Pool',
  allowUnauthenticatedIdentities: false,
  cognitoUsers: [
    cognito.UserPoolAuthenticationProvider.userPool(userPool, userPoolClient)
  ]
});

修正方案2:修复CfnIdentityPool的providerName参数

如果坚持使用底层构造,将providerName替换为用户池的ARN:

const identityPool = new cognito.CfnIdentityPool(this, 'MyIdentityPool', {
  identityPoolName: 'My Identity Pool',
  allowUnauthenticatedIdentities: false,
  cognitoIdentityProviders: [{
    clientId: userPoolClient.ref,
    providerName: userPool.userPoolArn, // 替换为用户池ARN
    serverSideTokenCheck: true // 建议添加,增强安全性
  }]
});

额外提示

  • 原代码中API Gateway安全组的Ingress规则配置错误:API Gateway的IP地址并非固定的restApiId.execute-api...格式,无法通过该方式限制访问。如果需要API Gateway访问VPC内的EC2,建议使用API Gateway VPC端点或者将EC2放在公有子网并使用弹性IP,同时开放对应端口给0.0.0.0/0(或更窄范围)。
  • 尽量优先使用CDK的L2构造(如UserPoolClient、IdentityPool),而非底层Cfn*构造,减少手动配置错误。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:01:30