3

I am trying to allow access to a Kinesis video stream using Cognito Identity Pools, but get an AccessDeniedException when calling GetDataEndpoint.

IAM Role Policy Doc:

{
    "Sid": "Stream",
    "Effect": "Allow",
    "Action": [
        "kinesisvideoarchivedmedia:GetHLSStreamingSessionURL",
        "kinesisvideo:GetDataEndpoint"
        ],
    "Resource": "arn:aws:kinesisvideo:us-west-2:XXXXXXXXXXXX:stream/<stream-name>/<stream-id>"
}

I have tested the policy using the policy simulator, and it shows that the GetDataEndpoint action is allowed on the stream, but when testing it in the browser the access denied exception occurs:

AccessDeniedException: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role//CognitoIdentityCredentials is not authorized to perform: kinesisvideo:GetDataEndpoint on resource: <resource-name>

This is how I'm getting the temporary credentials on the site:

AWS.config.region = 'us-west-2';AWS.config.credentials = new AWS.CognitoIdentityCredentials({
     IdentityPoolId: <identity-pool>,
});

AWS.config.credentials.get(function (err, data) {
    if (!err) {
        id = AWS.config.credentials.identityId;
        accessKey = AWS.config.credentials.accessKeyId;
        secretKey = AWS.config.credentials.secretAccessKey;
        token = AWS.config.credentials.sessionToken;
    }
});

I've tried using wildcards for the Kinesis video actions and the resource, but still get the same errors. Any advice would be appreciated.

Kate Orlova
  • 3,225
  • 5
  • 11
  • 35
Laura Kay
  • 31
  • 4

3 Answers3

1

This will be due to the scope down policy that Cognito applies to unauthenticated users. It is further explained here: https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html

As stated in the above documentation:

If you need access to something other than these services for your unauthenticated users, you must use the basic authentication flow.

callo
  • 1,374
  • 8
  • 12
1

To easily solve this you should also pass the unauthenticated role RoleArn to CognitoIdentityCredentials.

AWS.config.credentials = new AWS.CognitoIdentityCredentials({
     IdentityPoolId: <identity-pool>,
     RoleArn: <unauthorizedRoleArn>
});

This will ensure that, as specified here,

If a RoleArn is provided, then this provider gets credentials using the AWS.STS.assumeRoleWithWebIdentity() service operation, after first getting an Open ID token from AWS.CognitoIdentity.getOpenIdToken()

This essentially means that the credentials will be provided using the Basic (Classic) Flow

In addition to this you should also Allow Basic (Classic) Flow in your Identity Pool Authentication flow settings

kirtap
  • 121
  • 1
  • 5
1

I know this is old but I struggled with this for hours and couldn't get it to work even with RoleArn: <unauthorizedRoleArn> and following the suggestions in this issue.

In my case, my users are already authenticated via Amplify.Auth.signIn() but I needed to use AWS.KinesisVideo() which isn't included in the amplify sdk.

Ended up using the pre-generated AWSCrendentials post signIn. Might not be the best approach but it does the job.

const checkCognitoUserSession = async () => {
  const getAwsCredentials = await Auth.currentCredentials();
  const awsCredentials = await Auth.essentialCredentials(getAwsCredentials);

  return awsCredentials;
}; 

 const awsCredentials = await checkCognitoUserSession();

  AWS.config.update({
     credentials: new AWS.Credentials({
        accessKeyId: awsCredentials.accessKeyId,
        secretAccessKey: awsCredentials.secretAccessKey,
        sessionToken: awsCredentials.sessionToken,
     }),
  });

 new AWS.KinesisVideo({ apiVersion: '2017-09-30', region: config.Auth.region });
O.O
  • 1,389
  • 14
  • 29