I want to create a member-only page using Cognito and S3. I was able to sign up and sign in with Cognito, but I don't know the S3 setting that only the signed in user can access. I hope S3 can only be accessed by authenticated roles created during the creation of Cognito. How do I do that?
3 Answers
To control the access using IAM role, one option is using Cognito Identity Pool, after sigining in to Cognito User Pool and get JWT token.
Present the JWT token to Identity Pool and get AWS STS token which is tied to an IAM role you set up in Cognito Identity Pool.
Please refer to Accessing AWS Services Using an Identity Pool After Sign-in
Please be aware of the the difference between User Pool and Identity Pool as they are different services yet under the same name "Cognito" which can be confusing.
User Pool is just another authentication service like auth0, or Google, Facebook. We will not expect that we can control AWS resource access with the token which Google or Auth0 gives when we logged in there. Likewise, we cannot control the access to AWS resources with the token which User Pool provides when we sign-in to User Pool.
Amazon document is quite ambiguous on this and often mixes up User Pool and Identity Pool in the same document, causing confusions.
To be able to control the AWS resource access, we needs IAM Role and AWS STS token, which has nothing to do with User Pool itself basically (as with Google, Auth0, etc).
What we need is a mechanism to link the User Pool token to IAM role. There are a few options.
Use Cognito Identity Pool Identity Pool is exactly the service for this purpose.
Use Cognito User Pool Group mapping to IAM Role.
Alternatively, we can use AWS javasdcript SDK to directly get STS token by assuming a role and use it.
Again, please be careful with Amazon documentation talking about both User Pool and Identity Pool. Personally, they should not mix up difference services in the same document. User Pool is just another Identity Token Provider service like Auth0, but Identity Pool is a service to map external token like Google, Auth0, or Userpool to IAM role.
If sticking to User Pool JWT token, another alternative could be using API Gateway Cognito User Pool authorizer. Setup an API Gateway which only User Pool authenticated users can access and the API Gateway serves S3 web contents.
Also ALB has the external identity provider authentication option. This can be used to allow access only to the User Pool authenticated users.

- 18,789
- 22
- 112
- 205
It may be rude and misguided, but how exactly do you access S3 as follows?
const cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
cognitoUser.getSession(function(err, result) {
if (result) {
console.log('You are now logged in.');
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: "us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx': result.getIdToken().getJwtToken()
}
});
// Can't access it like this?
window.location.href = "https://xxxxxxxxxxxxxxxxxxxxxx.s3.amazonaws.com/private/index.html";
}
});
}

- 131
- 10
The bucket policy is as follows.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::<your-bucket-name>/*"
},
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "<your-user-arn>"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::<your-bucket-name>/*"
}
]
}

- 131
- 10