3

I have an Amplify App using Nuxt. When a user logs in via cognito the app tries to use STS to transfer to another role to get a QuickSight Dashboard Embed Url following this AWS blog post.

So I have a role with this policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "quicksight:GetDashboardEmbedUrl",
            "Resource": "arn:aws:quicksight:us-west-2:xxxxxxxx:dashboard/xxxx-xxxx-xxxxx-xxxx-xxxxxxxxxxxxx",
            "Effect": "Allow"
        }
    ]
}

and I added this policy to my app-authenticated-role

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::xxxxxxxxx:role/embed_role_name"
    }
}

When they log in via cognito I attempt to assume the embed_role with STS

with:

let params = {
    RoleArn: QS_EMBED_ROLE,
    RoleSessionName: "embedding-qs",
};

let sts = new AWS.STS();

sts.assumeRole(params, function (err, data) {
    if (err) console.log(err, err.stack);
    // an error occurred
    else {
        console.log(data);
    }
});

I get this error:

AccessDenied: User: arn:aws:sts::xxxxxxxxxx:assumed-role/app-authenticated-role/CognitoIdentityCredentials is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::xxxxxxxxxxxxx:role/embed_role

It seems pretty straight-forward in the docs so I'm not sure if I'm just not understanding something.

Also, in the course of trying a million things I think I edited the Trust Relationships for both the app-authenticated-role and embed-role and am not sure if it matters one way or the other.

The app-authenticated-role trust policy is:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-2:xxxxxxxx-xxxxxx-xxxxxx-xxxx-xxxxxxxx"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "authenticated"
        }
      }
    }
  ]
}

and the embed_role trust policy is:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-2:xxxxxxxx-xxxxxx-xxxxxx-xxxx-xxxxxxxx"
        }
      }
    }
  ]
}
halfer
  • 19,824
  • 17
  • 99
  • 186
av0000
  • 1,917
  • 6
  • 31
  • 51

2 Answers2

1

The reason this was not being authorized is because I needed to use the action

"Action": "sts:AssumeRole"

in my policy for my app-authenticated-role trust policy instead of

"Action": "sts:AssumeRoleWithWebIdentity"

Once that was replaced it worked as expected.

av0000
  • 1,917
  • 6
  • 31
  • 51
0

If you are using a Cognito Identity Pool to map an authenticated user to an IAM role, then rather than call sts:AssumeRole directly, you would normally use AWS.CognitoIdentityCredentials() to get IAM credentials for your web identity.

This makes 2 calls behind the scenes. Firstly, it uses the given Login (a JWT token from an Identity Provider such as Cognito User Pools, Facebook, Google, etc) to create a new identity, or retrieve an existing one. Secondly, it will call sts:AssumeRoleWithWebIdentity on your behalf and return IAM credentials.

This is all described in the Cognito Identity Pool docs.

So your authenticated role trust policy would be:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-2:xxxxxxxx-xxxxxx-xxxxxx-xxxx-xxxxxxxx"
        },
        "ForAnyValue:StringLike": {
          "cognito-identity.amazonaws.com:amr": "authenticated"
        }
      }
    }
  ]
}

which states that Cognito Identity can call STS to get credentials on behalf of a web identity.

The permissions policy associated with that role would be:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "quicksight:GetDashboardEmbedUrl",
            "Resource": "arn:aws:quicksight:us-west-2:xxxxxxxx:dashboard/xxxx-xxxx-xxxxx-xxxx-xxxxxxxxxxxxx",
            "Effect": "Allow"
        }
    ]
}

plus whatever other permissions your web user should have.

lemming
  • 1,753
  • 14
  • 12