Perfsys Logo
AWS IoT Core MQTT real-time messaging — 3D cinematic signal transmission symbol on dark navy background
Cognito AWS IoT

Integrating AWS IoT Core MQTT with Cognito Identity Pools

Published on Sep 9, 2024

pattern

Integrating real-time messaging between frontend and backend services is a key requirement for many modern applications. AWS IoT Core MQTT provides a robust solution for such communication needs, especially in Internet of Things (IoT) scenarios.

Configuring AWS IoT Core with Cognito Identity Pools can be complex, particularly when dealing with authenticated and unauthenticated roles. This guide explores the setup process, common issues, and troubleshooting steps for using AWS IoT Core MQTT with a React application, along with a detailed look at the application’s architecture.

Application Architecture Overview

Frontend: React Application

Hosting: The React application is hosted using AWS S3 and distributed via CloudFront for low latency and high availability.

AWS Amplify: The frontend leverages AWS Amplify for streamlined interactions with AWS services, including authentication via Cognito and messaging via IoT Core MQTT.

Communication: The React app communicates with the backend over HTTPS, ensuring secure data transmission between the client and server.

Backend: Python Application using AWS CDK

API Gateway: The backend uses AWS API Gateway to expose RESTful endpoints that facilitate communication with the frontend. It acts as the entry point for all API requests from the React application.

Lambda Integrations: AWS Lambda functions process requests and execute backend logic, offering a serverless approach that scales automatically with demand.

Real-Time Messaging: MQTT notifies the frontend when specific events occur — such as when a user payment is processed. This real-time capability allows dynamic updates to the website, such as removing a paywall once a payment is confirmed.

Deployment Context

Multiple websites, particularly video streaming landing pages, are deployed using this architecture. They all interact with the same backend to maintain consistency and reduce redundancy.

AWS IoT Core MQTT is used for real-time messaging, crucial for delivering instant feedback to users, such as payment confirmations.

Setting Up AWS IoT Core MQTT with Cognito Identity Pools

Cognito Identity Pools manage user identities and provide access to AWS services based on assigned roles. In this setup, both authenticated and unauthenticated roles were configured, each with permissions to connect, subscribe, receive, and manage policies within AWS IoT Core.

Cognito Identity Pools: These pools handle user identities and allocate permissions to AWS services. Both authenticated and unauthenticated roles are set up in the Identity Pool.

Permissions: Roles are granted the permissions required for interacting with AWS IoT Core: iot:Connect, iot:Subscribe, iot:Receive, and iot:AttachPrincipalPolicy.

Authenticated vs. Unauthenticated Roles: The unauthenticated role allows users to connect without logging in, while the authenticated role is used for logged-in users via Cognito User Pools.

Common Issue: AUTHORIZATION_FAILURE with Authenticated Roles

A frequent issue in this configuration is the failure of the authenticated role to connect, resulting in an AUTHORIZATION_FAILURE error — despite seemingly correct permissions. This issue typically does not affect the unauthenticated role, which functions as expected.

Problem Analysis: The failure occurs because the authenticated user’s identity does not have a specific IoT Core policy directly attached. Although both roles share similar permissions, the authenticated role requires the IoT policy to be explicitly linked to the identity for MQTT connections to work correctly.

Step-by-Step Solution

To resolve this, an IoT Core policy must be attached to the authenticated identity. The steps below outline how this can be achieved.

Retrieving the Cognito Identity ID

Obtaining the Cognito Identity ID is necessary to attach the IoT Core policy to the authenticated user. This ID is passed to the backend for further processing.

Attaching the IoT Core Policy Using AWS Lambda

A Lambda function handles policy attachment dynamically at the point of authentication. It retrieves the Cognito Identity ID from the request, then calls attach_policy via boto3 to link the IoT Core policy to that specific identity.

import boto3

def attach_iot_policy(event, context):
    iot = boto3.client('iot')
    cognito_identity_id = event['identity_id']
    policy_name = 'YourIoTPolicy'

    response = iot.attach_policy(
        policyName=policy_name,
        target=cognito_identity_id
    )
    return response

A few things to note:

  • identity_id must be the full Cognito Identity ID in the format region:uuid — passing just the UUID will cause a silent failure
  • The Lambda execution role must include iot:AttachPrincipalPolicy — without it, the call fails with an access denied error even if the Cognito role permissions look correct
  • Call this function once per authenticated session on login — not on every MQTT connect attempt

For reference, see the AWS boto3 IoT documentation and the AWS IoT Core policy documentation .

Updating Permissions

Ensure that the authenticated role includes the iot:AttachPrincipalPolicy permission, which allows the policy to be attached to the identity. Without it, the Lambda function will fail, causing continued authorization errors.

Validation and Testing

After applying these configurations, thorough testing should confirm that both authenticated and unauthenticated users can connect to AWS IoT Core MQTT successfully.

Best Practices and Recommendations

Role Permissions Management: Check the permissions associated with each role carefully. Authenticated roles in particular need an IoT policy directly attached to the user identity for MQTT communication.

Using AWS Amplify with PubSub: AWS Amplify can simplify the process, but it is important to manage identity roles and policies meticulously — especially when dealing with authenticated and unauthenticated users across shared browser sessions.

Debugging Authorization Failures: Authorization failures usually signal missing permissions or improperly attached policies. Reviewing role policies and ensuring correct attachment procedures are essential steps.

Policy Management: Use AWS IAM and IoT policies efficiently to manage access, aligning roles with the necessary permissions to avoid unnecessary overhead and potential security risks.

See This Architecture in Practice

If you want to see how Lambda, API Gateway, Cognito, and Amplify come together in a real production build, read our AI Mental Health Assistant MVP case study . Perfsys built a fully serverless AWS product that achieved over 90% cost reduction and delivered an investor-ready platform from scratch.

Conclusion

Navigating AWS IoT Core MQTT and Cognito can be intricate, especially when integrating real-time messaging and role-based access. The architecture described in this guide — Lambda, API Gateway, Cognito, and IoT Core — is one Perfsys deploys regularly for clients building event-driven, scalable products on AWS.

If you are looking to build something similar, our MVP Development Services are designed exactly for this: serverless-first, AWS-native, and built to scale from day one.

Talk to us about your project

Anastasiia Tokareva

Anastasiia Tokareva

Software Engineer

Explore Our Case Studies

View all Case Studies
Chevron right

AWS Experts, On-Demand

Need to move fast? Our cloud team is ready to scale, secure, and optimize your systems. Get serverless expertise, 24/7 support, and seamless CI/CD pipelines when you need it most.