How to use DynamoDB fine grained access control with Cognito User Pools?
Asked Answered
B

2

14

I'm having trouble understanding how to use fine-grained access control on DynamoDB when logged in using Cognito User Pools. I've followed the docs and googled around, but for some reason I can't seem to get it working.

My AWS setup is listed below. If I remove the condition in the role policy, I can get and put items no problem, so it seems likely that the condition is the problem. But I can't figure out how or where to debug policies that depend on authenticated identities - what variables are available, what are their values, etc etc.

Any help would be greatly appreciated!

DynamoDB table

  • Table name: documents
  • Primary partition key: userID (String)
  • Primary sort key: docID (String)

DynamoDB example row

{
  "attributes": {},
  "docID": "0f332745-f749-4b1a-b26d-4593959e9847",
  "lastModifiedNumeric": 1470175027561,
  "lastModifiedText": "Wed Aug 03 2016 07:57:07 GMT+1000 (AEST)",
  "type": "documents",
  "userID": "4fbf0c06-03a9-4cbe-b45c-ca4cd0f5f3cb"
}

Cognito User Pool User

  • User Status: Enabled / Confirmed
  • MFA Status: Disabled
  • sub: 4fbf0c06-03a9-4cbe-b45c-ca4cd0f5f3cb
  • email_verified: true

Role policy for "RoleName"

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:ap-southeast-2:NUMBER:table/documents"
            ],
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${cognito-identity.amazonaws.com:sub}"
                    ]
                }
            }
        }
    ]
}

Login information returned from cognitoUser.getUserAttributes()

attribute sub has value 4fbf0c06-03a9-4cbe-b45c-ca4cd0f5f3cb
attribute email_verified has value true
attribute email has value ****@****com

Error message

Code: "AccessDeniedException"
Message: User: arn:aws:sts::NUMBER:assumed-role/ROLE_NAME/CognitoIdentityCredentials is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:ap-southeast-2:NUMBER:table/documents
Backhanded answered 2/8, 2016 at 22:54 Comment(0)
T
23

The policy variable "${cognito-identity.amazonaws.com:sub}" is not the user sub which you get from Cognito user pools. It is in fact the identity id of a user which is generated by the Cognito Federated Identity service when you federate a user from Cognito User Pools with Federated identity service.

Since, the value in "${cognito-identity.amazonaws.com:sub}" never matches what you have in your DynamoDB row, it fails with AccessDenied. For this to work, the userId in your Dynamo entry should actually be the identity id, not sub. Currently, there is no direct link between IAM policy variables and Cognito User Pools service.

Here are some doc links which might help.
1. IAM roles with Cognito Federated Identity Service
2. Integrating User Pools with Cognito Federated Identity Service

Teetotal answered 3/8, 2016 at 8:50 Comment(7)
Thank you very much! For those who need a teensy bit more guidance, when a user logs in using Cognito Identity Pools, the string ${cognito-identity.amazonaws.com:sub} in IAM will resolve to the value found in AWS.config.credentials.identityId (which will look something like us-east-1:########-####-####-####-############).Backhanded
I am facing similar problem as described in #40447180. My primary key is same as cognito id but i am still getting the Unauthorised error.Faliscan
@Chetan Mehta: Do you know if there is anything planed on an implementation to use cognitoIdentityId as substitation variable? For my use case, I use the cognitoIdentityId as HASHKEY in DynamoDB and it would be good (from a security point of view) to use dynamodb:LeadingKeys with cognitoIdentityId as substituation variable for conditions in my policies (analogous to "Fine-Grained Access to Amazon DynamoDB": docs.aws.amazon.com/cognito/latest/developerguide/…).Inspectorate
@Chetan Mehta, I can get identityID in my api call after authentication. But how do I actually pass it on in my getObject? do i need to include it in the key prefix?Nashner
Is there any possible way that I can get the user's cognito pool sub inside the IAM policy docs? When the IAM role is only accessible via the identity pool?Vizza
Any news about it? Is it still not possible to use the user pools sub in an IAM policy?Priest
@Vizza @Priest it is possible by using PrincipalTag, see details in this answer #76673313Sharpsighted
S
0

Adding to Chetan's answer:

Currently, there is no direct link between IAM policy variables and Cognito User Pools service.

As of August 2023 (but I believe it had been possible even earlier), this statement is no longer true.

Contrary, it is indeed possible to map IAM policy variables to Cognito User Pool attributes (both standard and custom) via the PrincipalTag.

Yes, you can do that:

  1. Create a AWS::Cognito::IdentityPoolPrincipalTag with either default or custom mappings:

username (tag key) -> sub (claim)

  1. Use ${aws:PrincipalTag/username} in the IAM Policy:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Condition": {
                "ForAllValues:StringEquals": {
                    "dynamodb:LeadingKeys": [
                        "${aws:PrincipalTag/username}"
                    ]
                }
            },
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem"
            ],
            "Resource": "arn:aws:dynamodb:[REGION]:[ACCOUNT]:table/[TABLE]",
            "Effect": "Allow"
        }
    ]
}

The IAM snippet above will allow fine-grained access to DynamoDB table items. For example:

A Cognito User pool user with the sub attribute 4fbf0c06-03a9-4cbe-b45c-ca4cd0f5f3cb is able to access items with the primary key userID with the value: 4fbf0c06-03a9-4cbe-b45c-ca4cd0f5f3cb.

You can see details in my answer to a similar question.

Sharpsighted answered 3/8, 2023 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.