在本模块中,您将配置 Amazon Cognito,以将其用作应用程序中的身份验证提供商。Amazon Cognito 是完全托管的身份验证提供商,允许用户进行注册、验证、登录等操作。

Amazon Cognito 包括两种不同的组件:用户池身份池。用户池是标准的用户目录,在用户池中用户可以通过 Amazon Cognito 或第三方身份(如 GoogleGitHub)登录。成功通过身份验证后,用户会收到可用于访问后端资源的令牌,如访问令牌或 ID 令牌。

相比之下,身份池为用户提供了一种方式来接收用于访问 AWS 资源的临时 AWS 凭证。此凭证可用于有限直接地访问 AWS Lambda 函数、Amazon DynamoDB 表或其他资源。

在本教程中,您将使用 Amazon Cognito 用户池。您将允许用户通过您的应用程序进行注册。用户注册后,可以通过客户端登录以接收 ID 令牌。此 ID 令牌可作为标头传递到您的应用程序,以对用户进行身份验证。

在以下步骤中,您将创建一个 Amazon Cognito 用户池。然后,您将创建一个客户端来访问该用户池。最后,您将看到一些与用户池交互的示例代码。

完成模块所需时间:20 分钟


  • 第 1 步:创建 Amazon Cognito 用户池

    用户池是一个用户目录,所有用户和群组管理都在用户池中进行。创建用户池时,您需要为用户池指定规则,包括密码策略和必要属性。

    scripts/ 目录中,有一个名为 create-user-pool.sh 的文件。内容如下:

    USER_POOL_ID=$(aws cognito-idp create-user-pool \
      --pool-name inventory-users \
      --policies '
          {
          "PasswordPolicy": {
            "MinimumLength": 8,
            "RequireUppercase": true,
            "RequireLowercase": true,
            "RequireNumbers": true,
            "RequireSymbols": false
          }
        }' \
      --query 'UserPool.Id' \
      --output text)
    
    echo "User Pool created with id ${USER_POOL_ID}"
    echo "export USER_POOL_ID=${USER_POOL_ID}" >> env.sh

    此脚本使用 AWS 命令行界面 (AWS CLI) 创建用户池。您将用户池命名为 inventory-users ,并指定密码策略。此脚本要求密码的最小长度为 8 个字符,并且密码必须包括大写字母、小写字母和数字。

    您可以使用以下命令执行脚本,以创建用户池:

    bash scripts/create-user-pool.sh

    您应该能看到以下输出:

    User Pool created with id <user-pool-id>

    在下一步中,您将创建一个客户端来访问该用户池。

  • 第 2 步:创建用户池客户端

    您已配置了用户池,现在您需要创建用户池客户端。 用户池客户端用于调用用户池上未经身份验证的方法,如注册和登录。

    可通过后端 Node.js 应用程序使用用户池客户端。要注册或登录,用户会向您的应用程序发出包含相关属性的 HTTP POST 请求。您的应用程序会使用用户池客户端,并将这些属性转发到您的 Amazon Cognito 用户池。然后,您的应用程序会返回正确数据或错误消息。

    scripts/ 目录中名为 create-user-pool-client.sh 的文件可用于创建用户池客户端。该文件的内容如下:

    source env.sh
    
    CLIENT_ID=$(aws cognito-idp create-user-pool-client \
      --user-pool-id ${USER_POOL_ID} \
      --client-name inventory-backend \
      --no-generate-secret \
      --explicit-auth-flows ADMIN_NO_SRP_AUTH \
      --query 'UserPoolClient.ClientId' \
      --output text)
    
    echo "User Pool Client created with id ${CLIENT_ID}"
    echo "export COGNITO_CLIENT_ID=${CLIENT_ID}" >> env.sh

    该脚本可为您新创建的用户池创建用户池客户端。它使用 ADMIN_NO_SRP_AUTH 流,该流可以在服务器端应用程序中使用。因为您正在处理服务器端流,所以不需要在客户端流中(如移动设备上或单页应用程序中)使用客户端密钥。

    使用以下命令运行脚本以创建用户池客户端:

    bash scripts/create-user-pool-client.sh

    您应该能看到以下输出:

    User Pool Client created with id <client-id>

    在本模块的最后一步,您将了解应用程序中使用的身份验证代码。

  • 第 3 步:查看身份验证代码

    您已创建了用户池和用于访问该用户池的客户端,现在让我们看看如何在应用程序中使用 Amazon Cognito。

    您项目的 application/ 目录中有一个名为 auth.js 的文件。此文件中包含一些适用于您的应用程序的身份验证帮助程序。该文件有三个核心函数。让我们依次看一下。

    第一个函数是 createCognitoUser,在 Amazon Cognito 中注册新用户时使用该函数。该函数如下所示:

    const createCognitoUser = async (username, password, email) => {
      const signUpParams = {
        ClientId: process.env.COGNITO_CLIENT_ID,
        Username: username,
        Password: password,
        UserAttributes: [
          {
            Name: 'email',
            Value: email
          }
        ]
      }
      await cognitoidentityserviceprovider.signUp(signUpParams).promise()
      const confirmParams = {
        UserPoolId: process.env.USER_POOL_ID,
        Username: username
      }
      await cognitoidentityserviceprovider.adminConfirmSignUp(confirmParams).promise()
      return {
        username,
        email
      }
    }

    该函数使用您在前面步骤中设置的 Amazon Cognito 客户端 ID,以及用户提供的用户名、密码和电子邮件,来创建新用户。此外,您可以立即确认用户,以便用户可以登录。通常,您可以选择一个已验证用户的电子邮件和/或手机号码的确认流程,以便您获取用户的联系方式。这不在本教程范围内,您只需自动确认新用户即可。

    第二个核心方法是 login 函数,当已注册的用户进行身份验证时使用该函数。代码如下所示:

    const login = async (username, password) => {
      const params = {
        ClientId: process.env.COGNITO_CLIENT_ID,
        UserPoolId: process.env.USER_POOL_ID,
        AuthFlow: 'ADMIN_NO_SRP_AUTH',
        AuthParameters: {
          USERNAME: username,
          PASSWORD: password
        }
      }
      const { AuthenticationResult: { IdToken: idToken } }= await cognitoidentityserviceprovider.adminInitiateAuth(params).promise()
      return idToken
    }

    像在 createCognitoUser 函数中一样,您可以使用客户端 ID 和给定的参数来调用 Amazon Cognito。如果传递了身份验证方法,Amazon Cognito 的 adminInitiateAuth 方法会对用户进行身份验证并返回令牌。您可以使用 ID 令牌进行身份验证,因此这就是您针对用户成功登录所返回的内容。

    最后是 verifyToken 函数。此函数的内容如下:

    const verifyToken = async (idToken) => {
      function getKey(header, callback){
        client.getSigningKey(header.kid, function(err, key) {
          var signingKey = key.publicKey || key.rsaPublicKey;
          callback(null, signingKey);
        });
      }
    
      return new Promise((res, rej) => {
        jwt.verify(idToken, getKey, {}, function(err, decoded) {
          if (err) { rej(err) }
          res(decoded)
        })
      })
    }

    此函数可验证已随请求传递的 ID 令牌。Amazon Cognito 提供的 ID 令牌是 JSON Web 令牌,并且 verifyToken 函数会确认该令牌是否已由您的可信来源签名并用于标识用户。此函数用于要求身份验证的终端节点,以确保发出请求的用户拥有访问权限。

    在后续模块中,您将在后端应用程序中使用这三个身份验证函数。


在本模块中,您创建并配置了 Amazon Cognito 用户池以及该用户池的客户端。您还查看了一些实用函数,这些函数可与 Amazon Cognito 用户池交互以进行用户注册、登录和验证。

在下一个模块中,您将使用无服务器技术(如 AWS LambdaAmazon API Gateway)部署后端应用程序。