I want to connect to AWS IoT core from my iOS App. (MQTT over Websockets)

581 views Asked by At

I have an iOS app that collects accelerometer data from the iPhone sensors. I want to connect to the AWS IoT Core using MQTT over WSS from my ios app.

Question -> Is it mandatory to have an AWS IoT certificate in case I'm using Cognito?

I tried the below code using AWS SDK AWSMobileClient as mentioned on the link no luck though. The authenticated role has AWSIoTFullAccess, IoT policy to attached to identity ID as well using CLI command attach-policy

https://docs.amplify.aws/sdk/pubsub/working-api/q/platform/ios#aws-credentials-based-authentication

import Foundation
import UIKit
import AWSMobileClient
import AWSIoT
import AWSCore

class bulbViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        AWSMobileClient.default().initialize { (userState, error) in
            if let error = error{
                print(error.localizedDescription)
            }
            
            if let userState = userState{
                print("User state: \(userState.rawValue)");
            }
        }
        
        //getting JWT ID and ACCESS tokens
        AWSMobileClient.sharedInstance().getTokens { (tokens, error) in
            if let error = error {
                print("Error getting token \(error.localizedDescription)")
            } else if let tokens = tokens {
                print("========= Access Token ========")
                print(tokens.accessToken!.tokenString!)
                print("========= ID Token ========")
                print(tokens.idToken!.tokenString)
            }
        }
        //Create Logins map with the ID Token  to generate identity ID.
        
        AWSMobileClient.sharedInstance().getIdentityId().continueWith { task in
            if let error = task.error {
                print("error: \(error.localizedDescription) \((error as NSError).userInfo)")
                print(error)
            }
            if let result = task.result {
                print("identity id: \(result)")
            }
            return nil
        }
        
        // Initialize the AWSIoTDataManager with the configuration
        let iotEndPoint = AWSEndpoint(
            urlString: "wss://axxxxxxxazy1-ats.iot.us-west-2.amazonaws.com/mqtt")
        let iotDataConfiguration = AWSServiceConfiguration(
            region: AWSRegionType.USWest2,
            endpoint: iotEndPoint,
            credentialsProvider: AWSMobileClient.default()
        )

        AWSIoTDataManager.register(with: iotDataConfiguration!, forKey: "MyAWSIoTDataManager")
        let iotDataManager = AWSIoTDataManager(forKey: "MyAWSIoTDataManager")
        
        func mqttEventCallback(_ status: AWSIoTMQTTStatus ) {
            print("connection status = \(status.rawValue)")
        }

        iotDataManager.connectUsingWebSocket(withClientId: "iospubsubthing",
                                             cleanSession: true,
                                             statusCallback: mqttEventCallback)
        
        iotDataManager.publishString(
        "Hello to all subscribers!",
        onTopic: "myTopic",
        qoS:.messageDeliveryAttemptedAtMostOnce)
        
        
    }
    
}

output

User state: signedIn
identity id: us-west-2:878a197f-2dd9-4604-ae17-beXXXXX2747

connection status = 1
connection status = 5
connection status = 5
connection status = 1
connection status = 1
connection status = 5
connection status = 5
connection status = 5
connection status = 1


Corresponds to below.


typedef NS_ENUM(NSInteger, AWSIoTMQTTStatus) {
    AWSIoTMQTTStatusUnknown,
    AWSIoTMQTTStatusConnecting,
    AWSIoTMQTTStatusConnected,
    AWSIoTMQTTStatusDisconnected,
    AWSIoTMQTTStatusConnectionRefused,
    AWSIoTMQTTStatusConnectionError,
    AWSIoTMQTTStatusProtocolError
};

--------- AWS CW IoT Logs -----------------

{
    "timestamp": "2021-05-17 06:56:33.660",
    "logLevel": "ERROR",
    "traceId": "ada53b6c-b019-64c4-c074-66fe4XXX1d",
    "accountId": "635XXXXXX",
    "status": "Failure",
    "eventType": "Connect",
    "protocol": "MQTT",
    "clientId": "iospubsubthing",
    "principalId": "AROXXXXIICG6AYBSVWS:CognitoIdentityCredentials",
    "sourceIp": "103.XX1.1X0.20X",
    "sourcePort": 54036,
    "reason": "AUTHORIZATION_FAILURE",
    "details": "Authorization Failure"
}

Can you please tell us if I am missing anything over here?

1

There are 1 answers

0
Lucas Meier On

To debug: you can try to use Congito un-authenticated access first, giving the un-authenticated assumed Cognito Role the same rights as the authenticated one. If it works fine, is means you have an issue with attaching the IoT Policy to the Cognito Identity ID. To solve this issue, follow my recent post on how to attach IoT Policies to Cognito Identities.

In fact, you don't need to attach the IoT Policy to un-authenticated users. It may help you debug !