繁体   English   中英

使用 Web 套接字与 Cognito 身份验证用户连接到 AWS IoT

[英]connect to AWS IoT using web socket with Cognito authenticated users

我正在尝试使用来自浏览器的 Web 套接字连接到 AWS IoT。

我试过这个例子: https : //github.com/awslabs/aws-iot-examples/tree/master/mqttSample

另一个稍微修改了一下,以便它可以与 Cognito 身份池登录的用户一起使用。 https://github.com/dwyl/learn-aws-iot/blob/master/src/js/utils/request.js#L27

如果我使用具有有效 IoT 策略的 IAM 用户,我可以成功连接,但如果我使用用户凭据,我会收到“101 交换协议”响应,但随后它会关闭。

与经过身份验证的用户关联的 IAM 角色是正确的,我可以签署请求并执行其他私有操作,例如调用 APIG 端点。 此外,套接字连接不响应 403。所以它可能不是权限问题。

还能是什么?

对于未经身份验证的认知身份,“身份池已身份验证”角色足以允许连接到物联网 MQTT 代理。 但是,对于经过身份验证的认知身份,需要做两件事:

  1. “身份池已验证”角色必须允许访问您需要的 IoT 操作(例如连接、发布等)。

  2. 您必须使用AttachPrincipalPolicy API将 IoT 策略(与附加到您的设备的策略完全一样)附加到认知身份

第 2 步是我今天早些时候陷入困境的地方,因为在任何地方都不是特别清楚需要这样做。

AFAIK 无法从任何 AWS 网站将 IoT 策略附加到认知用户。 但是,如果您的机器上安装了 AWS 命令​​行界面,则可以从那里进行设置。 命令看起来像:

aws iot attach-principal-policy --policy-name <iot-policy-name> --principal <cognito-identity-id>

可以使用Federated Identities > Your Pool > Identity browser找到认知身份 ID,或者您也可以在对CognitoIdentityCredentials.get调用的响应中找到它。 它看起来像这样us-east-1:ba7cef62-f3eb-5be2-87e5-fffbdeed2824

对于生产系统,您显然希望自动附加此策略,可能在用户注册时使用 lambda 函数。

可以在此页面上找到有关需要附加 IoT 策略的文档部分:

要使经过身份验证的 Amazon Cognito 身份通过 HTTP 在您的 AWS 账户中的 topic1 上发布 MQTT 消息,您必须指定两个策略,如此处所述。 第一个策略必须附加到 Amazon Cognito 身份池角色并允许来自该池的身份进行发布调用。 第二个策略使用 AWS IoT AttachPrincipalPolicy API 附加到 Amazon Cognito 用户,并允许指定的 Amazon Cognito 用户访问 topic1 主题。

为了在前端实现 Caleb 的回答,我必须做几件事:

  1. 通过转到 IoT 控制台 > 安全性 > 策略并将AWSIoTDataAccess策略内容复制并粘贴到AWSIoTDataAccess来创建 IoT 策略(名为“默认”)
  2. 将以下内联策略添加到我的 Cognito 身份池的经过身份验证的角色: {"Effect": "Allow", "Action": ["iot:AttachPrincipalPolicy"], "Resource": ["*"]

然后我更新了我的前端代码,如下所示:

AWS.config.region = process.env.AWS_REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: process.env.AWS_IDENTITY_POOL,
  Logins: {
    'graph.facebook.com': FACEBOOK_ACCESS_TOKEN
  }
});
AWS.config.credentials.get(() => {
  const IoT = new AWS.Iot();
  IoT.attachPrincipalPolicy({
    policyName: 'default',
    principal: AWS.config.credentials.identityId
  }, (err, res) => {
    if (err) console.error(err);
    // Connect to AWS IoT MQTT
  });
});

这是一个代码示例,用于将 IoT 策略从 Lambda (NodeJS) 函数附加到 Cognito 用户 ID。

function attachPrincipalPolicy(device_id, cognito_user_id) {
    const iotMgmt = new AWS.Iot();
    return new Promise(function(resolve, reject) {
        let params = {
            policyName: device_id + '_policy',
            principal: cognito_user_id
        };
        console.log("Attaching IoT policy to Cognito principal")
        iotMgmt.attachPrincipalPolicy(params, (err, res) => {
            if (err) {
                console.error(err);
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

我参考了 Caleb 和 senornestor 的答案,以下实现对我有用:

AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: AWSConfiguration.poolId,
  Logins: {
     'accounts.google.com': user.Zi.id_token
  }
});

var cognitoIdentity = new AWS.CognitoIdentity();

AWS.config.credentials.get(function(err, data) {
  if (!err) {
     console.log('retrieved identity: ' + AWS.config.credentials.identityId);

     var params = {
        IdentityId: AWS.config.credentials.identityId,
        Logins: {
           "accounts.google.com": user.Zi.id_token
        }
     };
     cognitoIdentity.getCredentialsForIdentity(params, function(err, data) {
        if (!err) {
           console.log('retrieved credentials');
           const IoT = new AWS.Iot();
           IoT.attachPrincipalPolicy({
              policyName: 'exampleIoTPolicy',
              principal: AWS.config.credentials.identityId
           }, (err, res) => {
              if (err) console.error(err);
           });  // Change the "policyName" to match your IoT Policy
        } else {
           console.log('error retrieving credentials: ' + err);
           alert('error retrieving credentials: ' + err);
        }
     });
  } else {
     console.log('error retrieving identity:' + err);
     alert('error retrieving identity: ' + err);
  }
});

这是一个示例应用程序,它应该有助于演示如何使用 Cognito 对 IoT 进行身份验证:

https://github.com/awslabs/aws-iot-chat-example

有关明确的说明,您可以阅读:

https://github.com/awslabs/aws-iot-chat-example/blob/master/docs/authentication.md

事实证明,即使在 2021 年,也有必要创建一个专用的 Lambda 函数来执行AttachPolicy (不是AttachPrincipalPolicy因为它已过时)。 正如官方文档中所述

要将 AWS IoT Core 策略附加到 Amazon Cognito 身份,您必须定义一个调用 AttachPolicy 的 Lambda 函数。

其他答案展示了如何实现该 Lambda。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM