首页 文章

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

提问于
浏览
15

我正在尝试使用浏览器中的Web套接字连接到AWS IoT .

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

另一个有点修改,因此它可以与Cognito Identity Pool登录用户一起使用 . https://github.com/dwyl/learn-aws-iot/blob/master/src/js/utils/request.js#L27

如果我使用具有有效IoT策略的IAM用户,我可以成功连接,但如果我使用用户凭据,则会收到“101 Switching Protocols”响应,但随后会关闭 .

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

还有什么呢?

5 回答

  • 8

    对于未经身份验证的Cognito身份,“Identity pool anauthenticated”角色足以允许连接到IoT MQTT代理 . 然而,对于经过身份验证的认知身份,需要做两件事:

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

    • 您必须使用AttachPrincipalPolicy API将IoT政策(与您的设备相关联的政策)附加到身份识别身份

    第2步是我今天早些时候被困住的地方,因为在任何地方都不是特别清楚这是必需的 .

    AFAIK无法将物联网策略附加到来自任何AWS网站的Cognito用户 . 但是,如果您在计算机上安装了AWS命令行界面,则可以从那里进行设置 . 该命令如下所示:

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

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

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

    有关需要附加IoT政策的文档部分可以在this page找到:

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

  • 4

    为了在前端实现Caleb的答案,我不得不做几件事:

    • 通过转到IoT控制台>安全性>策略并将 AWSIoTDataAccess 策略内容复制并粘贴到其中来创建IoT策略(名为"default")

    • 将以下内联策略添加到Cognito Identity Pool的身份验证角色: {"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
      });
    });
    
  • 0

    我参考了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);
      }
    });
    
  • 2

    以下是从Lambda(NodeJS)函数将IoT策略附加到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();
                }
            });
        });
    }
    
  • 16

    以下示例应用程序应该有助于演示如何使用Cognito对IoT进行身份验证:

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

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

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

相关问题