How can I attach an IoT Core policy to a Cognito Identity Id on a post authentication Lambda trigger for an Amplify deployed web application?

0

Situation:

I have a ReactJS web application that is deployed through AWS Amplify and uses Amplify Studio backend to handle authentication through Cognito services and aws-amplify sdk (sign in, sign up).

The web application also implements the use of react native aws-amplify sdk pubsub to subscribe to an MQTT topic in IoT Core and retrieve messages but only to authenticated users.

As per step 2 in the pubsub documentation: Attach your policy to your Amazon Cognito Identity.

If I use the AWS CLI to attach the IoT policy to the user and then I sign in with that user through the web application I am able to successfully subscribe and receive MQTT messages -- it works perectly!

Problem:

The application allows Cognito self-service user sign up (Self-registration) and expects to have many users.

I implemented a post authentication lambda trigger function in the Cognito user pool created by the Amplify service.

The lambda function runs the following sample from AWS documentation with two (2) additional console logs:

exports.handler = (event, context, callback) => {

    // Send post authentication data to Cloudwatch logs
    console.log ("Authentication successful");
    console.log ("Trigger function =", event.triggerSource);
    console.log ("User pool = ", event.userPoolId);
    console.log ("App client ID = ", event.callerContext.clientId);
    console.log ("User ID = ", event.userName);

*** console.log("Event = ", event);
    console.log("Context = ", context);***

    // Return to Amazon Cognito
    callback(null, event);
};

I then authenticate with the user again through the application and go to CloudWatch logs for that Lambda function.

This is the information I get from logging Event and Context after post authentication trigger:

Event log:

{
  version: '1',
  region: 'us-east-1',
  userPoolId: 'us-east-1_*********',
  userName: '4eea4a48-92b6-45da-b26e-*********',
  callerContext: {
    awsSdkVersion: 'aws-sdk-unknown-unknown',
    clientId: '*********'
  },
  triggerSource: 'PostAuthentication_Authentication',
  request: {
    userAttributes: {
      sub: '4eea4a48-92b6-45da-b26e-*********',
      'cognito:email_alias': '*********.com',
      'cognito:user_status': 'CONFIRMED',
      email_verified: 'true',
      name: 'asdfasdf',
      email: '*********.com'
    },
    newDeviceUsed: false
  },
  response: {}
}

Context log:

{
  callbackWaitsForEmptyEventLoop: [Getter/Setter],
  succeed: [Function (anonymous)],
  fail: [Function (anonymous)],
  done: [Function (anonymous)],
  functionVersion: '$LATEST',
  functionName: 'userAccess_iotCore_attachPolicyToCognitoIdentityID',
  memoryLimitInMB: '128',
  logGroupName: '/aws/lambda/userAccess_iotCore_attachPolicyToCognitoIdentityID',
  logStreamName: '2023/01/13/[$LATEST]4eb4287aa4db4dd8a6b6efd810a7***',
  clientContext: undefined,
  identity: undefined,
  invokedFunctionArn: 'arn:aws:lambda:us-east-1:*********:function:userAccess_iotCore_attachPolicyToCognitoIdentityID',
  awsRequestId: 'bf6afd1c-117c-4a9e-9d3b-*********',
  getRemainingTimeInMillis: [Function: getRemainingTimeInMillis]
}

The big issue here is that context.identity is undefined so I am not able to get that authenticated user's Amazon Cognito Identity Id to attach the required IoT policy for PubSub to work through the application. Questions:

How can I get the Amazon Cognito Identity Id after post authentication trigger to then attach an IoT policy?

From the web application using the aws-amplify sdk I am able to get this Id after sign in. Is there any API I can use from the application to attach this policy?

Thanks.

1 Answer
0

With what you have done you successfully got OAuth2 credentials in the form of JSON Web Tokens [aka JWTs]. there are 3:

  • Identity Token: that contains the user profile in a signed JSON object
  • Access Token: some entitlements information in a signed JSON object
  • Refresh Token: long lived opaque string allowing to get new Access Token

But those are not AWS IAM Credentials. They cannot be used against AWS native API.

You need to create a Cognito IDentity Pool to exchange an Identity Token for Temporary AWS IAM Credentials. Cognito Identity Pool will give you options on which IAM role will be assumed as part of the Temporary AWS IAM Credentials issuance. The IAM Policy for Pub/Sub would have to be assigned to the IAM role assumed through Cognito Identity Pool.

AWS
answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions