Business Productivity

Creating read-only chat channels for announcements with Amazon Chime SDK messaging

Amazon Chime SDK messaging provides the building blocks needed to build chat and other real-time messaging features. Available APIs include sending messages, retrieving message history, editing messages, deleting messages, setting retention policies on stored messages, and streaming chat export. These APIs are combined with the Amazon Chime SDK for JavaScript and managed messaging infrastructure so developers don’t have to worry about building and scaling their own.

In this blog, you will learn how to create read-only channels that can be used to broadcast announcements to users. Announcement channels are helpful for a number of different use cases including for enterprise chat applications that want a single channel to send announcements to employees, for education applications that want to send messages to students or teachers, and for application developers that want to engage their customers. This blog covers two different ways to create read-only channels. In example one, we cover the ability to add hidden members to a private channel. These hidden members can read messages in the channel, but they cannot see other members in the same channel, or send messages to the channel. In example two, user privileges are restricted in rooms that are tagged as ‘ReadOnly’, thereby preventing users from sending or updating messages.

Pre-requisites

For this walkthrough, you should have the following pre-requisites:

Setting up your environment

For simplicity, we will be starting with the chat demo app covered in the Build chat features into your application with Amazon Chime SDK messaging blog post. Before continuing with this blog, you should follow the steps there to get the demo app up and running, and save the AppInstanceARN from Step 1.

Please note your AWS account will be charged for usage of the services used by the demo app.

Once you have the demo app up and running, to prepare your environment to complete the two examples in this blog post, you will also need to follow these steps to set up your environment:

  1. Create an IAM user with developer access for Amazon Chime SDK messaging
  2. Create an AppInstanceAdmin to run admin APIs
  3. Create a server policy for your IAM user with developer access
  4. Create the IAM policy for your AppInstanceAdmin with a trust policy so that your IAM user can assume the AppInstanceAdmins role

The IAM user with developer access is used to run developer APIs, like creating app instance users, and to run AWS Security Token Service (AWS STS) commands to assume the role of your AppInstanceAdmin to run administrator commands. When using these two users, it is easiest to have two sessions open in your terminal. If your terminal supports tabs, you can open two tabs to create two separate sessions. One session is used for your developer user, and the other for the AppInstanceAdmin.

Creating an IAM user with developer access for Amazon Chime SDK messaging

Once you have the demo app up and running, you will also want to make sure you have an IAM user with access to Amazon Chime SDK messaging, you cannot use your Root user.

Create a new IAM policy called AmazonChimeSDKMessagingDev:

  1. Open the Identity and Access Management (IAM) Console
  2. In the left navigation, choose Policies
  3. Choose Create Policy
  4. Select the JSON tab
  5. In the text area paste the policy below
  6. Choose Next:Tags
  7. Choose Next:Review
  8. Enter the name AmazonChimeSDKMessagingDev
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "chime:CreateAppInstance",
                    "chime:DescribeAppInstance",
                    "chime:ListAppInstances",
                    "chime:UpdateAppInstance",
                    "chime:DeleteAppInstance",
                    "chime:CreateAppInstanceUser",
                    "chime:DeleteAppInstanceUser",
                    "chime:ListAppInstanceUsers",
                    "chime:UpdateAppInstanceUser",
                    "chime:DescribeAppInstanceUser",
                    "chime:CreateAppInstanceAdmin",
                    "chime:DescribeAppInstanceAdmin",
                    "chime:ListAppInstanceAdmins",
                    "chime:DeleteAppInstanceAdmin",
                    "chime:PutAppInstanceRetentionSettings",
                    "chime:GetAppInstanceRetentionSettings",
                    "chime:PutAppInstanceStreamingConfigurations",
                    "chime:GetAppInstanceStreamingConfigurations",
                    "chime:DeleteAppInstanceStreamingConfigurations",
                    "chime:TagResource",
                    "chime:UntagResource",
                    "chime:ListTagsForResource"
                ],
                "Effect": "Allow",
                "Resource": "*"
            }
        ]
    }
  9. Choose Create Policy
  10. In the left navigation, choose Users
  11. Select Add User
  12. Enter the name AmazonChimeSDKMessagingDev
  13. Select the checkbox for Programmatic Access
  14. Choose Next:Permissions
  15. Choose Attach existing policies directly
  16. Attach each of the policies below:
    1. IAMFullAccess
    2. AmazonS3FullAccess
    3. AmazonChimeSDKMessagingDev (Managed Policy)
  17. Select Next:Tags
  18. Choose Next:Review
  19. Choose Create User
  20. Download and save the user credentials to configure the AWS CLI

Creating your app instance admin to run admin APIs

Once you have AmazonChimeSDKMessagingDev user created, configure the AWS CLI to use AmazonChimeSDKMessagingDev and us-east-1 and then create an AppInstanceAdmin.

Via CLI, create a user (John)

aws chime create-app-instance-user --app-instance-arn "<AppInstanceArnYouSavedFromDemoApp>" --name "John" --app-instance-user-id "John"

This will return an AppInstanceUserARN, save it.

Promote the user (‘John’) to AppInstanceAdmin

aws chime create-app-instance-admin --app-instance-arn "<AppInstanceArnYouSavedFromDemoApp>" --app-instance-admin-arn "<JohnsArn>"

Creating a server policy for your IAM user with developer access

To enable your AmazonChimeSDKMessagingDev user to assume the role of your AppInstanceAdmin, you will need to create a server policy and attach it to the AmazonChimeMessagingDev user. Create the policy below and attach it to your AmazonChimeSDKMessagingDev user. Follow the same steps used previously to create the policy and attach it to the AmazonChimeSDKMessagingDev user.

To create the policy and attach it to the user:

  1. Open the Identity and Access Management (IAM) Console
  2. In the left navigation, choose Policies
  3. Choose Create Policy
  4. Select the JSON tab
  5. In the text area paste the policy below and update with your AWS account id
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "sts:AssumeRole",
                    "sts:TagSession"
                ],
                "Resource":"arn:aws:iam::<YOURAWSACCOUNTID>:role/ChimeMessagingUserRole"
            }
        ]
    }
  6. Choose Next:Tags
  7. Choose Next:Review
  8. Enter the name ChimeSampleAppServerPolicy
  9. Choose Create Policy
  10. In the left navigation choose Users
  11. Click on AmazonChimeSDKMessagingDev
  12. Choose Add Permissions
  13. Choose Attach Existing Policies Directly
  14. Search for then select ChimeSampleAppServerPolicy
  15. Choose Add Permissions

Creating an IAM user role with user policy for your AppInstanceAdmin and trust relationship with the AmazonChimeMessagingDev role

So that you are able to assume the role of John from the AWS CLI, you need to create a new IAM role. We will call this role ChimeMessagingUserRole and assign it the ChimeMessagingUserPolicy below.

  1. Open the IAM Console
  2. In the left navigation select Policies
  3. Choose Create Policy
  4. Select the JSON tab and paste the policy below
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "chime:GetMessagingSessionEndpoint"
                ],
                "Resource": [
                    "*"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "chime:SendChannelMessage",
                    "chime:ListChannelMessages",
                    "chime:CreateChannelMembership",
                    "chime:ListChannelMemberships",
                    "chime:DeleteChannelMembership",
                    "chime:CreateChannelModerator",
                    "chime:ListChannelModerators",
                    "chime:DescribeChannelModerator",
                    "chime:CreateChannel",
                    "chime:DescribeChannel",
                    "chime:ListChannels",
                    "chime:DeleteChannel",
                    "chime:RedactChannelMessage",
                    "chime:UpdateChannelMessage",
                    "chime:Connect",
                    "chime:ListChannelBans",
                    "chime:CreateChannelBan",
                    "chime:DeleteChannelBan",
                    "chime:ListChannelMembershipsForAppInstanceUser"
                ],
                "Resource": [
                    "<AppInstanceArnYouSavedFromDemoApp>/user/${aws:PrincipalTag/username}",
                    "<AppInstanceArnYouSavedFromDemoApp>/channel/*"
                ]
            }
        ]
    }

    Replace the AWS Account ID and AppInstanceArn with your AWS Account ID and your AppInstanceArn

  5. Select Next:Tags
  6. Select Next:Review
  7. Enter ChimeMessagingUserPolicy as the policy name
  8. Choose Create Policy
  9. In the left navigation select Roles
  10. Choose Create Role
  11. For the type of entity, select Another AWS Account
  12. For the Account ID, enter your own account ID.
  13. Choose Next:Permissions
  14. Search for and select ChimeMessagingUserPolicy
  15. Choose Next:Tags
  16. Choose Next:Review
  17. For role name enter ChimeMessagingUserRole
  18. Choose Create Role

The ChimeMessagingUserRole then needs to have a trust relationship set up with the ChimeSampleAppServerRole

Still in the IAM console:

  1. Open the ChimeMessagingUserRole
  2. Select the Trust Relationships tab
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::<YOURAWSACCOUNTID>:user/AmazonChimeSDKMessagingDev"
          },
          "Action": [
            "sts:AssumeRole",
            "sts:TagSession"
          ]
        }
      ]
    }
  3. Choose Edit trust relationship
  4. Choose JSON and paste the policy below, making sure to add your own AWS Account ID
  5. Choose Update Trust Policy

Once these steps are complete, you are ready to move on to the examples.

Example One: Creating a private channel with hidden members

When you add new members to channels using CreateChannelMembership, you have the option to add them as ‘HIDDEN.’ When added as hidden, users do not show up as members when other members call ListChannelMemberships. This is useful for bots that need access to channel messages, but don’t need to interact with other members. It can also be useful for support use cases where managers may need to monitor ongoing conversations, but not participate. Because hidden members cannot send messages, using this option also works for creating read-only channels, and has the added benefit of keeping other members private.

Steps

  1. Open your demo app in your browse https://localhost:9000
  2. Using the sign in/registration page, create a user ‘Jane’ and verify her in Amazon Cognito using the steps provided in the Build chat features into your application with Amazon Chime SDK messaging post. Follow the same process to create a user ‘Mary’.
  3. Open your terminal and as the AmazonChimeSDKMessagingDev user, use AWS STS to assume the role of John, your AppInstanceAdmin. It is recommended to run the STS command in one tab, and then open another tab to run the commands as John.aws sts assume-role --role-arn "arn:aws:iam::<YOURAWSACCOUNTID>:role/ChimeMessagingUserRole" --role-session-name John —tags Key=username,Value=John
  4. After you run this command, credentials will be returned that include an AccessKeyID, SecretAccessKey, and SessionToken. Open a second terminal tab, and run the following commands with the values returned by STS assume-role to change the credentials used by the AWS CLI. Once this is done, the second terminal tab can be used to run commands as John.

    export AWS_ACCESS_KEY_ID=<key_goes_here>

    export AWS_SECRET_ACCESS_KEY=<key_goes_here>
    export AWS_SESSION_TOKEN=<key_goes_here>
  5. Now, in the terminal tab you are using to run commands as John, create a new Private channel called ‘Read-Only Example One’ and make it Private and Restricted.aws chime create-channel --app-instance-arn "<AppInstanceArnYouSavedFromDemoApp>" --name "Announcements Example One" --privacy "PRIVATE" --mode "RESTRICTED" --chime-bearer "<JohnsArn>"Save the channel ARN.
  6. Add your users Jane and Mary to the channel as hidden members.aws chime list-app-instance-users —app-instance-arn "<AppInstanceArnYouSavedFromDemoApp>"
  7. Grab the AppInstanceUserArn for Jane and Mary and run this command once for each user with each of their ARNs.aws chime create-channel-membership --channel-arn "<AppInstanceArnYouSavedFromDemoApp>" --member-arn "<UserArn>" --chime-bearer "<JohnsArn>" —type HIDDEN
  8. As your AppInstanceAdmin send a channel message into the channelaws chime send-channel-message --channel-arn "<SavedChannelArn>" --type "STANDARD" --persistence "PERSISTENT" --content "Hey folks" —chime-bearer "<JohnsArn>"
  9. As one of your users, sign in to the demo app and confirm the user has access to the channel and the messages, but cannot send.

To keep this demonstration simple, we have not modified the UI to reflect that status of the channel as a Broadcast or Read-Only channel. In a production application, you should make it clear to users that the channel is different so they understand why they are unable to send messages.

Example Two: Denying access to SendChannelMessage and UpdateChannelMessage for channels tagged as ‘ReadOnly’

In Amazon Chime SDK messaging, after a user is authenticated, AWS IAM policies are vended to users and define which APIs they have access to and on which resources. This access can include all APIs within the scope of their assigned role, or a subset of them. This policy can also be used to grant more access or less access on specific resources, such as channels. Using this ability to scope down access is an alternative means of creating read-only channels for announcements.

The steps to create read-only channels with scoped down IAM policies are:

  1. Modify the CognitoAuthorizedPolicy created for the demo app with a condition that only grants access to SendChannelMessage and UpdateChannelMessage if channels are not tagged as ‘ReadOnly’
  2. Create a new private channel and tag it with the resource tag ‘ReadOnly’
  3. Add users to the channel by running this command for Jane and Mary
  4. As your AppInstanceAdmin send a channel message into the channel
  5. As one of your users, sign in to the demo app and confirm the user has access to the channel and the messages, but cannot send.

Modify the IAM policy created for the users in the demo app

To eliminate the ability for users to send or update messages in channels labeled as ReadOnly, you will need to modify the IAM policy created with the CloudFormation template for the demo application. This policy will be updated so that access to SendChannelMessage and UpdateChannelMessage is only granted if channels are not tagged as ‘ReadOnly’

You can find this policy by:

  1. Opening the CloudFormation console
  2. Choosing amazon-chime-sdk-chat-demo-app under the list of stacks.
  3. Under resources, choose the link next to CognitoAuthorizedRole
  4. Attached to this role you will find the ChimeSDKMessagingDemo-ChimeSDKDemoUserPolicy 

Below you will find the entire policy, but rather than copy and pasting the policy below and replacing the values in brackets with your own AWS Account ID, Cognito Identity Pool ID, and App Instance ARN you can alternatively just add the condition for the resource tag for SendChannelMessage and UpdateChannelMessage and remove both of those actions from the top section.

ChimeSDKMessagingDemo-ChimeSDKDemoUserPolicy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "chime:GetMessagingSessionEndpoint"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cognito-idp:ListUsers"
            ],
            "Resource": "<CognitoPoolARN>",
            "Effect": "Allow"
        },
        {
            "Action": [
                "chime:ListChannelMessages",
                "chime:CreateChannelMembership",
                "chime:ListChannelMemberships",
                "chime:DeleteChannelMembership",
                "chime:CreateChannelModerator",
                "chime:ListChannelModerators",
                "chime:DescribeChannelModerator",
                "chime:CreateChannel",
                "chime:DescribeChannel",
                "chime:ListChannels",
                "chime:UpdateChannel",
                "chime:DeleteChannel",
                "chime:RedactChannelMessage",
                "chime:Connect",
                "chime:ListChannelMembershipsForAppInstanceUser",
                "chime:CreateChannelBan",
                "chime:ListChannelBans",
                "chime:DeleteChannelBan",
                "chime:TagResource"
            ],
            "Resource": [
                "<YourAppInstanceArn>/user/${cognito-identity.amazonaws.com:sub}",
                "<YourAppInstanceArn>/channel/*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "chime:SendChannelMessage",
                "chime:UpdateChannelMessage"
            ],
            "Resource": [
                "<YourAppInstanceArn>/user/${cognito-identity.amazonaws.com:sub}",
                "<YourAppInstanceArn>/channel/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:ResourceTag/readonly": [
                        "true"
                    ]
                }
            },
            "Effect": "Allow"
        }
    ]
}

Create a new private channel and tag it with the resource tag ‘ReadOnly’

aws chime create-channel --app-instance-arn "<SavedChannelArn>" --name "Announcements Example Two" --privacy "PRIVATE" --mode "RESTRICTED" --tags Key="readonly",Value="true" --chime-bearer "<JohnsArn>"

Save the channel ARN

Add users to the channel by running this command for Jane and Mary

aws chime create-channel-membership --channel-arn "<AppInstanceArnYouSavedFromDemoApp>" --member-arn "<UserArn>" --chime-bearer "<JohnsArn>" --type HIDDEN

As your AppInstanceAdmin send a channel message into the channel

aws chime send-channel-message --channel-arn "<SavedChannelArn>" --type "STANDARD" --persistence "PERSISTENT" --content "Hello again folks" --chime-bearer "<JohnsArn>"

As one of your users, sign in to the demo app and confirm the user has access to the channel and the messages, but cannot send.

Again, with this example we have not modified the user interface to let users know why the channel is different than others. As a next step, you can modify the interface to show that the channel is for announcements, and remove or disable UI components like the text field for sending messages.

Cleanup

If you don’t want to continue to be charged for the use of the chat demo application, you can clean up by deleting the stack and resources created in step 2 of the Build chat features into your application with Amazon Chime SDK messaging blog post.
.

To delete the stack and its resources:

  1. From the AWS CloudFormation console in the Region, select the stack that you created.
  2. Click Delete Stack.
  3. In the confirmation message that appears, click Yes, Delete. At this stage, the status for your changes to DELETE_IN_PROGRESS. In the same way you monitored the creation of the stack, monitor its deletion by using the Events tab. When AWS CloudFormation completes the deletion of the stack, it removes the stack from the list.

Finally, delete your Amazon Chime app instance using the following commands in AWS CLI:

aws chime delete-app-instance --app-instance-arn <AppInstanceArnYouSavedFromDemoApp>

Conclusion

With Amazon Chime SDK messaging, customers are easily able to build and customize their own messaging capabilities for their applications. They don’t have to worry about the heavy lifting of managing and scaling a complex infrastructure. In this blog post, you learned how to create read-only channels for broadcast announcements.

The Amazon Chime SDK messaging features are available today in the US East (N. Virginia) region at low per-message rates. To get started with Amazon Chime SDK messaging, read our developer guide.