Skip to content

User: arn:aws:sts::<ACCOUNT_ID>:assumed-role/<ROLE_NAME>/CognitoIdentityCredentials is not authorized to perform: kinesisvideo:GetSignalingChannelEndpoint on resource: arn:aws:kinesisvideo:<REGION>

0

Issue: Unauthorized to perform kinesisvideo:GetSignalingChannelEndpoint

I am trying to build a POC where a doorbell camera (master) streams video to an app (viewer) using Amazon Kinesis Video Streams (WebRTC). However, I keep getting an unauthorized error when calling GetSignalingChannelEndpoint.


What I Did

  1. Created a Kinesis Video Streams Signaling Channel

    • Example name: test_doorbell

    • ARN format:

      arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>
      
  2. Created a Cognito Identity Pool (unauthenticated guest access)

    • Identity Pool ID:

      <region>:<identity-pool-id-uuid>
      
  3. Created IAM Role for unauth users (automatically generated by Cognito).

    • Attached custom policies (tried different variations, see below).

Policies I Tried

Policy 1 – Wildcard resources

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["cognito-identity:GetCredentialsForIdentity"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:DescribeSignalingChannel",
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:ConnectAsViewer"
      ],
      "Resource": "*"
    }
  ]
}

Policy 2 – Resource with /*

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["cognito-identity:GetCredentialsForIdentity"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:ConnectAsViewer",
        "kinesisvideo:GetIceServerConfig"
      ],
      "Resource": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/*"
    }
  ]
}

Policy 3 – Full channel ARN with ID

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["cognito-identity:GetCredentialsForIdentity"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:SendAlexaOfferToMaster",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:ConnectAsViewer"
      ],
      "Resource": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>"
    }
  ]
}

Code Snippet

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Doorbell POC</title>
</head>
<body>
  <h2>Door Cam / Viewer POC</h2>

  <label>Mode: </label>
  <select id="modeSelect">
    <option value="master">Door Cam (Master)</option>
    <option value="viewer">App Cam (Viewer)</option>
  </select>
  <button id="startBtn">Start</button>

  <div style="margin-top:20px;">
    <video id="localVideo" autoplay muted playsinline width="400"></video>
    <video id="remoteVideo" autoplay playsinline width="400"></video>
  </div>

  <script type="module" src="app.js"></script>
</body>
</html>

app.js

import {
  CognitoIdentityClient,
  GetIdCommand,
  GetCredentialsForIdentityCommand
} from "https://cdn.jsdelivr.net/npm/@aws-sdk/client-cognito-identity/+esm";

import {
  KinesisVideoClient,
  GetSignalingChannelEndpointCommand
} from "https://cdn.jsdelivr.net/npm/@aws-sdk/client-kinesis-video/+esm";

import {
  KinesisVideoSignalingClient,
  GetIceServerConfigCommand
} from "https://cdn.jsdelivr.net/npm/@aws-sdk/client-kinesis-video-signaling/+esm";

const REGION = "<region-name>"; 
const IDENTITY_POOL_ID = "<region-name>:<identity-pool-id-uuid>";
const CHANNEL_ARN = "arn:aws:kinesisvideo:<region-name>:<account-id>:channel/<channel-name>/<channel-id>";

async function getAWSCredentials() {
  const cognitoClient = new CognitoIdentityClient({ region: REGION });

  const idData = await cognitoClient.send(
    new GetIdCommand({ IdentityPoolId: IDENTITY_POOL_ID })
  );

  const credData = await cognitoClient.send(
    new GetCredentialsForIdentityCommand({ IdentityId: idData.IdentityId })
  );

  return {
    accessKeyId: credData.Credentials.AccessKeyId,
    secretAccessKey: credData.Credentials.SecretKey,
    sessionToken: credData.Credentials.SessionToken
  };
}

async function getKVSEndpoints(creds, role) {
  const kvClient = new KinesisVideoClient({ region: REGION, credentials: creds });

  const endpointData = await kvClient.send(
    new GetSignalingChannelEndpointCommand({
      ChannelARN: CHANNEL_ARN,
      SingleMasterChannelEndpointConfiguration: {
        Protocols: ["WSS"],
        Role: role // "MASTER" or "VIEWER"
      }
    })
  );

  const wssEndpoint = endpointData.ResourceEndpointList[0].ResourceEndpoint;

  const kvsSignalingClient = new KinesisVideoSignalingClient({
    region: REGION,
    credentials: creds,
    endpoint: wssEndpoint
  });

  const iceData = await kvsSignalingClient.send(new GetIceServerConfigCommand({}));

  const iceServers = iceData.IceServerList.map(server => ({
    urls: server.Uris,
    username: server.Username,
    credential: server.Password
  }));

  return { wssEndpoint, iceServers };
}

async function start(mode) {
  const creds = await getAWSCredentials();
  const role = mode === "master" ? "MASTER" : "VIEWER";
  const { wssEndpoint, iceServers } = await getKVSEndpoints(creds, role);

  const pc = new RTCPeerConnection({ iceServers });

  if (mode === "master") {
    const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
    document.getElementById("localVideo").srcObject = localStream;
  }

  pc.ontrack = event => {
    document.getElementById("remoteVideo").srcObject = event.streams[0];
  };

  const ws = new WebSocket(wssEndpoint);

  ws.onopen = async () => {
    if (mode === "master") {
      const offer = await pc.createOffer();
      await pc.setLocalDescription(offer);
      ws.send(JSON.stringify({ sdp: offer }));
    }
  };

  ws.onmessage = async msg => {
    const data = JSON.parse(msg.data);
    if (data.sdp) {
      await pc.setRemoteDescription(data.sdp);
      if (mode === "viewer") {
        const answer = await pc.createAnswer();
        await pc.setLocalDescription(answer);
        ws.send(JSON.stringify({ sdp: answer }));
      }
    }
  };
}

document.getElementById("startBtn").onclick = () => {
  const mode = document.getElementById("modeSelect").value;
  start(mode);
};

Error I Get

API Request

POST https://kinesisvideo.ap-south-1.amazonaws.com/getSignalingChannelEndpoint

Payload:
{
  "ChannelARN": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>",
  "SingleMasterChannelEndpointConfiguration": {
    "Protocols": ["WSS"],
    "Role": "VIEWER"   // or "MASTER"
  }
}

Response

{
  "Message": "User: arn:aws:sts::<account-id>:assumed-role/<role-name>/CognitoIdentityCredentials is not authorized to perform: kinesisvideo:GetSignalingChannelEndpoint on resource: arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>"
}

My Question

Even after trying multiple policy variations (*, /*, full ARN with channel ID), I still get "not authorized".

  • Am I using the correct resource ARN format for Kinesis Video signaling channels?
  • Do I need to explicitly allow both DescribeSignalingChannel and GetSignalingChannelEndpoint?
  • Is there something missing in how the Cognito unauthenticated role should be set up?

Any guidance would be appreciated.

3 Answers
1
Accepted Answer

You are using the correct resource ARN format for Kinesis Video signaling channels:
arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>

However, the unauthorized error is usually due to one of these issues:

1. IAM Policy Resource ARN

  • For GetSignalingChannelEndpoint, you must use the full channel ARN with the channel ID (not just /*).
  • Example:
    "Resource": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>"
    

2. Required Actions

  • You must allow both DescribeSignalingChannel and GetSignalingChannelEndpoint (and others you need).
  • Example:
    "Action": [
      "kinesisvideo:DescribeSignalingChannel",
      "kinesisvideo:GetSignalingChannelEndpoint",
      "kinesisvideo:GetIceServerConfig",
      "kinesisvideo:ConnectAsMaster",
      "kinesisvideo:ConnectAsViewer"
    ]
    

3. Cognito Role Trust Policy

  • The unauthenticated role must trust the Cognito Identity Pool.
  • The trust policy should allow cognito-identity.amazonaws.com as the principal.

4. Identity Pool Role Mapping

  • Ensure your identity pool is set to allow unauthenticated identities and maps them to the correct IAM role.

5. Policy Attachment

  • The policy must be attached to the unauthenticated role (not the authenticated one).

6. Propagation Delay

  • IAM changes can take a few minutes to propagate. Wait a few minutes after updating policies.

Checklist

  • [x] Full channel ARN with channel ID in the policy resource.
  • [x] All required actions allowed.
  • [x] Trust policy for unauthenticated role includes Cognito Identity Pool.
  • [x] Identity pool allows unauthenticated identities and maps to correct role.
  • [x] Policy attached to unauthenticated role.
  • [x] Waited for IAM changes to propagate.

Example IAM Policy (for unauthenticated role)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cognito-identity:GetCredentialsForIdentity"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:DescribeSignalingChannel",
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:ConnectAsViewer"
      ],
      "Resource": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>"
    }
  ]
}

Trust Policy Example

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "<identity-pool-id>"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "unauthenticated"
        }
      }
    }
  ]
}

Troubleshooting Steps

  1. Double-check the resource ARN in your policy matches the channel ARN (with channel ID).
  2. Confirm the unauthenticated role trust policy is correct.
  3. Make sure the policy is attached to the unauthenticated role.
  4. In the AWS Console, use the IAM Policy Simulator to test the role against the GetSignalingChannelEndpoint action.
  5. Wait a few minutes after making changes.

If you follow these steps and still get the error, please provide:

  • The exact IAM policy attached to the unauthenticated role.
  • The trust policy for the role.
  • The identity pool role mapping configuration.

Answer to your questions Based on your detailed description of the Kinesis Video Streams WebRTC authorization issue, let me answer your specific questions:

1. Am I using the correct resource ARN format for Kinesis Video signaling channels?

Yes, you are using the correct format:

arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>

This is the proper ARN format for Kinesis Video Streams signaling channels.

2. Do I need to explicitly allow both DescribeSignalingChannel and GetSignalingChannelEndpoint?

Yes, you should include both actions. While GetSignalingChannelEndpoint is the primary action causing the error, AWS services sometimes perform internal calls that require additional permissions. Your Policy 1 with wildcard resources was actually the closest to being correct.

Here's the recommended policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["cognito-identity:GetCredentialsForIdentity"],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:DescribeSignalingChannel",
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:ConnectAsViewer"
      ],
      "Resource": "arn:aws:kinesisvideo:<region>:<account-id>:channel/<channel-name>/<channel-id>"
    }
  ]
}

3. Is there something missing in how the Cognito unauthenticated role should be set up?

Most likely yes. The issue is probably in one of these areas:

A. Trust Policy

Your unauthenticated role needs this trust policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "<your-identity-pool-id>"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "unauthenticated"
        }
      }
    }
  ]
}

B. Identity Pool Configuration

In your Cognito Identity Pool:

  1. Enable "Enable access to unauthenticated identities"
  2. Under "Unauthenticated role", select your IAM role
  3. Make sure the role is properly attached

C. Role Attachment

Ensure your policy is attached to the unauthenticated role (not authenticated role) in the Cognito Identity Pool settings.

Most Common Issues:

  1. Policy attached to wrong role - Make sure it's on the unauthenticated role
  2. Missing trust policy - The role must trust cognito-identity.amazonaws.com
  3. Identity Pool not configured for unauthenticated access - Must be enabled
  4. IAM propagation delay - Wait 5-10 minutes after making changes

Quick Diagnostic Steps:

  1. In AWS Console → Cognito → Identity Pools → Your Pool → Edit
  2. Verify "Enable access to unauthenticated identities" is checked
  3. Note the "Unauthenticated role" ARN
  4. Go to IAM → Roles → Find that role
  5. Check both the trust policy and attached policies
  6. Verify your custom policy is attached to this specific role

The fact that you're getting a specific "not authorized" error (rather than authentication failure) suggests the Cognito credentials are working, but the IAM permissions on the assumed role are insufficient.

EXPERT

answered a year ago

EXPERT

reviewed a year ago

  • Hello Adeleke Adebowale Julius

    First of all, thank you so much for your support and continuous guidance.

    I have tried all the things you mentioned above, and this time I used the AWS test page — but I am still getting the same issue.

    Link to my issue

    My detailed question on re:Post

1

The issue is that your current policy uses wildcard actions (kinesisvideo:*) but AWS requires explicit permissions for Kinesis Video Streams signaling operations. Here's the corrected policy:

Fixed IAM Policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cognito-identity:*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "kinesisvideo:GetSignalingChannelEndpoint",
        "kinesisvideo:GetIceServerConfig",
        "kinesisvideo:SendAlexaOfferToMaster",
        "kinesisvideo:ConnectAsMaster",
        "kinesisvideo:ConnectAsViewer"
      ],
      "Resource": "arn:aws:kinesisvideo:<REGION>:<ACCOUNT_ID>:channel/<CHANNEL_NAME>/*"
    }
  ]
}

Key Changes Made:

  1. Separated Cognito and Kinesis Video permissions into different statements for better security
  2. Added explicit Kinesis Video Signaling permissions:
    • kinesisvideo:GetSignalingChannelEndpoint - The specific permission you're missing
    • kinesisvideo:GetIceServerConfig - Required for WebRTC signaling
    • kinesisvideo:ConnectAsMaster - If your app acts as master
    • kinesisvideo:ConnectAsViewer - If your app acts as viewer
  3. Scoped the resource to your specific channel instead of using wildcard

How to Apply This Fix:

  1. Find your Cognito Identity Pool's authenticated role:

    • Go to IAM Console → Roles
    • Look for a role like Cognito_<IdentityPoolName>Auth_Role
  2. Update the role's policy:

    • Click on the role → Permissions tab
    • Find the policy and click "Edit"
    • Replace with the corrected policy above
    • Replace <REGION>, <ACCOUNT_ID>, and <CHANNEL_NAME> with your actual values
  3. Alternative: Create a separate policy:

    • Create a new policy with the Kinesis Video permissions
    • Attach it to your Cognito authenticated role

Resource ARN Format:

Make sure to replace the placeholders:

  • <REGION>: Your AWS region (e.g., us-east-1)
  • <ACCOUNT_ID>: Your 12-digit AWS account ID
  • <CHANNEL_NAME>: Your Kinesis Video Signaling Channel name

If you want to allow access to all channels, you can use:

arn:aws:kinesisvideo:<REGION>:<ACCOUNT_ID>:channel/*

This should resolve your authorization error and allow your Cognito-authenticated users to access the Kinesis Video Signaling Channel endpoints.

EXPERT

answered a year ago

AWS
EXPERT

reviewed a year ago

  • Hello Adeleke Adebowale Julius,

    I have tried modifying the policy in different ways, but I am still encountering the same error. I have also updated my question with more detailed information about the issue. Could you please help me identify where I might be making a mistake?

    Thank you for your support.

  • can you check with the new update below and answer to your questions

0

Note: This is not a solution, From the two answers above I wasn’t able to resolve the issue. Since I cannot add a comment longer than 1500 characters, I am posting this as a separate answer and will paste this answer link in the above comment. and Master , MASTER was not accept as i added `` around


Kinesis channel ARN

arn:aws:kinesisvideo:ap-south-1:<account-id>:channel/doorbell_poc/<channel-id>

Identity Pool Name and ID

doorbell_poc
ap-south-1:4b8bddfd-AAAA-AAAA-AAAA-0e645904885c

Role ARN and Trust Policy

Role ARN:

arn:aws:iam::<account-id>:role/service-role/doorbell_poc

Role Name:

doorbell_poc

Trust Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "cognito-identity.amazonaws.com:aud": "ap-south-1:4b8bddfd-AAAA-AAAA-AAAA-0e645904885c"
                },
                "ForAnyValue:StringLike": {
                    "cognito-identity.amazonaws.com:amr": "unauthenticated"
                }
            }
        }
    ]
}

IAM Policy attached to Role

Policy Name:

Cognito-unauthenticated-1755515505261

Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cognito-identity:GetCredentialsForIdentity"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "kinesisvideo:DescribeSignalingChannel",
                "kinesisvideo:GetSignalingChannelEndpoint",
                "kinesisvideo:GetIceServerConfig",
                "kinesisvideo:ConnectAs`Master`",
                "kinesisvideo:ConnectAsViewer"
            ],
            "Resource": "arn:aws:kinesisvideo:ap-south-1:<account-id>:channel/doorbell_poc/<channel-id>"
        }
    ]
}

My Setup

I have my Node.js code which I used to get:

  • IdentityId → Client ID
  • AccessKeyId → Access Key ID
  • SecretKey → Secret Access Key
  • SessionToken → Session Token
  • Region → from my identity pool

I am using the AWS test page, Amazon Kinesis Video Streams WebRTC JS SDK Examples and when I click on Start Master or Start Viewer button I get this error:

Error

[2025-08-21T06:39:26.198Z] [ERROR] [ `MASTER`] Encountered error starting: {
  "name": "AccessDeniedException",
  "$fault": "client",
  "$metadata": {
    "httpStatusCode": 403,
    "requestId": "cc340917-28b6-44b6-82d7-edca23342ec7",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "message": "User: arn:aws:sts::<account-id>:assumed-role/doorbell_poc/CognitoIdentityCredentials is not authorized to perform: kinesisvideo:DescribeSignalingChannel on resource: doorbell_poc"
}
AccessDeniedException
    at So (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:132341)
    at yo (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:130503)
    at async https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:35152
    at async https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:36376
    at async https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:84151
    at async https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/aws-sdk-3.758.0-kvswebrtc.js:1:32440
    at async ChannelHelper._checkWebRTCIngestionPath (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/channelHelper.js:196:54)
    at async ChannelHelper._initializeClients (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/channelHelper.js:113:13)
    at async ChannelHelper.init (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/channelHelper.js:29:9)
    at async start`Master` (https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/`master`.js:92:9)

What I Tried

  1. After updating policy I waited for 30 mins
  2. From identity pool ID I navigate to its role and policy so they are connected

Question

Where am I making mistake?


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.

Relevant content