Allow cognito users to view images in s3

0

I have granted the Cognito user access to the S3 object matching that user attribute with Cognito Identity Pool.
How can I view images in a bucket from a URL in a browser logged in as the Cognito user?

What I want to

  • To split the s3 bucket into tenants and only allow image files from the tenant to which the Cognito user belongs to be viewed.
  • To display images with img tag <img src="">.

What I did

  • S3 object arn: arn:aws:s3:::sample-tenant-bucket/public/1/photos/test.jpg
  • Create Cognito User with custom attributes
aws cognito-idp admin-create-user \
  --user-pool-id "ap-northeast-1_xxxx" \
  --username "USER_NAME" \
  --user-attributes Name=custom:tenant_id,Value=1
  • Cognito Identity Pool
    • Mapping of user attributes to principal tags
      • "tenantId": "custom:tenant_id"
    • Added sts:TagSession permission to the authenticated role
    • Attach policy to the authenticated role
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "*",
            "Resource": "arn:aws:s3:::sample-tenant-bucket/public/${aws:PrincipalTag/tenantId}/*",
            "Effect": "Allow"
        }
    ]
}

Hypothesis

  1. Typing the object URL (https://sample-tenant-bucket.s3.ap-northeast-1.amazonaws.com/public/1/1670773819-1.jpg) into the address bar results in a 403, even when logged in with an AWS account as an administrator, not as a Cognito User. Therefore, I thought that Object URLs could not be used for non-public objects.
  2. The Presigned URL seems to work, but I was wondering if there is another way to do it, since it is a method that does not depend on whether the user is already logged in to the AWS account or not.
  3. Maybe this question is the same as asking how to display an image in a bucket by URL in a browser that is already logged in with the object owner's AWS account
1 Answer
0

Accessing an S3 URL directly, as in typing it in your browser's URL bar, will only ever work if the URL is signed, or if the S3 object is public (which you don't want in this case).

What you want I think, is to build a web application where you have JavaScript that (1) first uses the identity pool to get temporary AWS credentials using your Cognito User's credential (i.e. ID token) and then (2) uses the temporary AWS credentials to construct a signed URL. Then finally (3) use that signed url in the image element: <img src="...signed url..." />.

Here is some sample code from one of my apps, to give you an idea how to generate a signed URL. This uses the Amplify JS library that abstracts (1) away for you (this of cource only works if you use Amplify Auth in your JS app):

import { Auth } from "@aws-amplify/auth";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const S3 = new S3Client({
  credentialDefaultProvider: () => Auth.currentCredentials,
  region: process.env.REACT_APP_AWS_REGION,
});
const command = new GetObjectCommand({
  Bucket: process.env.REACT_APP_S3_BUCKET,
  Key: "<your key>",
});
const signedUrl = getSignedUrl(S3, command, { expiresIn: 3600 });
AWS
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.

Guidelines for Answering Questions